C # - Intercepting property changes in subclasses

I create a framework in which I provide a base class, and structure implementators inherit the base class and provide additional properties and methods. In the base class, I would like to be able to observe when the value of a property changes. The property can be from the base class or any of the subclasses. I know that through reflection I can define a list of properties from any instance, but is there a way to track the value of a property change?

Here is a very simplified example of what I am saying:

public class BaseClass { public string BaseClassProperty { get; set; } public void DoSomethingWhenEitherPropertyGetsChanged() { } } public class SubClass : BaseClass { public string SubClassProperty { get; set; } } 

What can I do to make DoSomethingWhenEitherPropertyGetsChanged execute when any of the properties change its value.

+7
source share
4 answers

You can use notifypropertyweaver for this purpose. He does exactly what you want. Here is the link:

On the open source homepage:

Uses an IL transform (via http://www.mono-project.com/Cecil ) to inject INotifyPropertyChanged code into properties.

  • No attributes required
  • No links required
  • No base class required
  • Supports .net 3.5, .net 4, Silverlight 3, Silverlight 4, Silverlight 5, and Windows Phone 7.
  • Client Profile Mode Support
+4
source

I would probably use Postsharp and create an inherited attribute that injects the interception code into all public properties. Marking an attribute as inherited should also automatically join all subclasses.

+3
source

I wrote my own idea of ​​your requirements, but I'm not sure if it fits your needs. The changes to INotifyProperty are something you could also explore, but I don't like it very much, because it looks like speghetti wiring. Perhaps this will give you some creative ideas.

What this means is that it allows you to use an ObservableObject as for all your property types. By doing this, each property will have an ObjectChanged event with which you can connect. Con is that you must initialize all your properties in the constructor to throw a NullReferenceException in your code.

This example uses three classes.

  • ObservableObject.cs
  • Employee.cs
  • Program.cs

ObservableObject.cs

  //----------------------------------------------------------------------------- // <copyright file="ObservableObject.cs" company="DCOM Productions"> // Copyright (c) DCOM Productions. All rights reserved. // </copyright> //----------------------------------------------------------------------------- namespace PropertyChangedEventExample { using System; public class ObservableObject : Object { /// <summary> /// Expose the default constructor /// </summary> public ObservableObject() { // No default implementation } private object m_Object = null; /// <summary> /// Base object /// </summary> public object Object { get { return m_Object; } set { if (m_Object != value) { m_Object = value; OnObjectChanged(this, EventArgs.Empty); } } } /// <summary> /// Triggered when the value of this object has changed. /// </summary> public event System.EventHandler<EventArgs> ObjectChanged; /// <summary> /// EventHandler wire-up /// </summary> protected virtual void OnObjectChanged(object sender, System.EventArgs e) { if (ObjectChanged != null) { ObjectChanged(sender, e); } } /// <summary> /// Gets the value /// </summary> public object Get() { return this.Object; } /// <summary> /// Sets the value /// </summary> public void Set(object value) { this.Object = value; } } } 

Employee.cs

  //----------------------------------------------------------------------------- // <copyright file="Employee.cs" company="DCOM Productions"> // Copyright (c) DCOM Productions. All rights reserved. // </copyright> //----------------------------------------------------------------------------- namespace PropertyChangedEventExample { using System; public class Employee { /// <summary> /// Expose default constructor /// </summary> public Employee() { Name = new ObservableObject(); } /// <summary> /// Gets or sets the name /// </summary> public ObservableObject Name { get; set; } } } 

Program.cs

  //----------------------------------------------------------------------------- // <copyright file="Program.cs" company="DCOM Productions"> // Copyright (c) DCOM Productions. All rights reserved. // </copyright> //----------------------------------------------------------------------------- namespace PropertyChangedEventExample { using System; class Program { static void Main(string[] args) { Employee employee = new Employee(); employee.Name.Set("David"); employee.Name.ObjectChanged += new EventHandler<EventArgs>(Name_ObjectChanged); employee.Name.Set("Dave"); Console.ReadKey(true); } static void Name_ObjectChanged(object sender, EventArgs e) { ObservableObject employee = sender as ObservableObject; Console.WriteLine("Name changed to {0}", employee.Get()); } } } 
+1
source

Best of all, CrisWue recommended and used postharp or some other post processor to inject behavior into your properties. Other than this, I think you will need to call DoSomethingWhenEitherPropertyGetsChanged () manually in your properties.

If you create a library that is consumed by people other than you or your organization, the postprocessor may not be the right way, because it adds a third-party tool as another requirement for their build process.

0
source

All Articles