This project is read-only.

Implementing Observable Objects

Implemention of INotifyPropertyChanged and INotifyPropertyChanging is provided for by the ObservableObject class.
This class provides all the infrastructure needed to implement change notifications, by using Lambda Expressions to implement property declarations. Consider the following code, which declares an observable Name property:
     public class Account : ObservableObject
     {
        public static Property<NotifyDummy, string> NameProperty = 
                   new Property<NotifyDummy, string>(
                      c => c.Name,                 // Lambda reference to Property...  survives refactoring
                      c => c._name,                // field getter
                      (c, v) => c._name = v);      // field setter

        private string _name;

        public string Name
        {
            get { return _name; }
            set { NameProperty.Set(this, value); }       // Compact property setter - implements change notifications
        }
The semantics of a property change are all handled by the generic Prop class. The Prop class will:
  • Check whether the new value is different from the existing value (and exit if unchanged).
  • Pass control back to the owning instance's DoSetProperty method, passing the correct stirng name of the property, the current value, the proposed new value, and a delegate for setting the _name field.
  • DoSetProperty (overridable) will
    • Check whether any listeners are attached to the PropertyChanged/PropertyChanging events
    • Fire the PropertyChangingEvent, providing listeners with the currnet nad proposed values.
    • Set the underlying field
    • Fire PropertyChanged, passing a strongly typed PropertyChangeEventArgs which features an undo method.

You can override DoSetProperty (the heart of the property change implementation) to provide logic of your own if you so wish.

You can also bypass the declared property pattern (shown above), and simply write your properties as:
     public class Account : ObservableObject
     {
        private string _name;

        public string Name
        {
            get { return _name; }
            set { 
               if(! string.Equals( _name, value) )
               {
                   DoSetProperty( "Name", _name, _value, newValue => _name = newValue);
               }
            }
        }
The entire framework is fully backward compatible with the usual property changed pattern, but opens the doors for more advanced scenarios.

Why not just use ActivSharp?
ActiveSharp is a very clever library, and uses pixie dust and three wishes to magically implement property change notifications. Put differently, ActiveSharp relies on CLR implementation details and magic pointers to work correctly. Admitedly, this results in cleaner user code (which is nice), at the expense of compiler optimizations. The pattern implemented in this library is 100% standard C# code, and while it is slightly more effort to implement each property, it is performant, and it allows the compiler to perform optimizations.

Last edited Oct 28, 2010 at 8:31 PM by maranite, version 4

Comments

No comments yet.