See also: Properties as objects
The goal here is to have a class with a property that implements the Observer pattern, based on a statement in Object Thinking that all classes should support this. (I’m not sure I agree, but I’m exploring it anyway.)
So far I’ve proposed two options:
Let the class support its own notifications of events. Downsides are:
Create a class to do it all for you. Downsides are:
Upon further discussion with members of the team, we’ve come up with something I like quite a bit. It balances responsibilities between the class you’re writing and the Property<> class. It seems to solve all the problems listed above.
Here’s the code:
interface IReadonlyProperty<T>
{
T Value { get; }
event Property<T>.SetEventHandler OnSet;
}
class Property<T> : IReadonlyProperty<T>
T _value;
public Property()
// put something into the event so that I don't have to check
// for null later.
this.OnSet += delegate { };
public delegate void SetEventHandler(object sender, T newValue);
public event SetEventHandler OnSet;
public T Value
get
return this._value;
set
this._value = value;
this.OnSet(this, this._value);
public void SetValueWithoutFiringEvent(T t) { this._value = t; }
T IReadonlyProperty<T>.Value { get { return this._value; } }
To demonstrate its worth, here’s the usage:
class Customer
Property<int> _age = new Property<int>();
public IReadonlyProperty<int> Age
get { return this._age; }
public void Test()
int eventFiredCount = 0;
this._age.OnSet += delegate { eventFiredCount++; };
Debug.Assert(eventFiredCount == 0);
this._age.Value = 9;
Debug.Assert(eventFiredCount == 1);
this._age.SetValueWithoutFiringEvent(7);
Note that I can still set the value internally to Customer without firing the event, but only by explicitly saying that’s what I’m doing. I could decide never to allow that by just removing the SetValueWithoutFiringEvent method.