ChainedPropertyObserver

The other day I was messing around with an idea I had where I had a object graph of related objects which looked something like this (where each object was an INotifyPropertyChanged object).

dbSchema

And I thought wouldn’t it be nice if I could observer changed from any of those object conveniently, and without the need to hook/unhook when new object were introduced into the object graph.

So I had a think and came up with a bunch of classes that do allow me to observe changes in a chain of objects, and do so in a kind of fault tolerant manner, where replacement objects could be brought into the chain, without any adverse affect to the INPC listeners.

The main class I came up with is called ChainPropertyObserver and can be used as simply as this:

//create INPC model
Person p = new Person();
p.Age = 12;
p.Name = "sacha";
p.Address = new Address() { 
    Addressline1="21 maple street",
    Addressline2 = "Hanover",
    GeoLocation = new GeoLocation 
        { 
            Longitude=0.555, 
            Latitude=0.787 
        } 
    };

MyPerson = p;

List<string> personChanges = new List<string>();
List<string> addressChanges = new List<string>();
List<string> geoLocationChanges = new List<string>();

//create observer
ChainPropertyObserver chainPropertyObserver = 
    new ChainPropertyObserver();
chainPropertyObserver.CreateChain(
    () => MyPerson.Address.GeoLocation, Changed);


//create some INPC listeners
chainPropertyObserver.RegisterChainLinkHandler(
    () => MyPerson,
    () =>
    {
        Console.WriteLine("The Person that changed is now : {0}", 
            MyPerson.ToString());
        personChanges.Add(MyPerson.ToString());
    });

chainPropertyObserver.RegisterChainLinkHandler(
    () => MyPerson.Address,
    () =>
    {
        Console.WriteLine("The Address that changed is now : {0}", 
            MyPerson.Address.ToString());
        addressChanges.Add(MyPerson.Address.ToString());
    });

chainPropertyObserver.RegisterChainLinkHandler(
    () => MyPerson.Address.GeoLocation,
    () =>
    {
        Console.WriteLine("The GeoLocation that changed is now : {0}", 
            MyPerson.Address.GeoLocation.ToString());
        geoLocationChanges.Add(MyPerson.Address.GeoLocation.ToString());

    });

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

If you want to know more you can read the full article over at codeproject at this url : http://www.codeproject.com/KB/cs/ChainedObserve.aspx

Advertisements

6 thoughts on “ChainedPropertyObserver

  1. mihailik says:

    Have a look at Obtics at CodePlex — the guys do all that in much simpler syntax.

    • sacha says:

      An interesting link there for sure, but not sure we are doing same thing. From their example, which they say does this:

      Make changes to the _People collection or the LastName properties of the individual People objects and PeoplesNames will get updated automatically (reactivity).

      public class Test
      {
      ObservableCollection _People;

      public IEnumerable PeoplesNames_Static
      {
      get
      {
      return
      from p in _People
      orderby p.LastName
      select p.LastName ;
      }
      }

      public IEnumerable PeoplesNames
      {
      get
      {
      return
      ExpressionObserver.Execute(
      this,
      t =>
      from p in t._People
      orderby p.LastName
      select p.LastName
      ).Cascade();
      }
      }
      }

      That is just firing the parent INPC when one of the child elements in the collection changes. That is not what my code is doing. And I could see nothing on the Obtics site that showed me how to do what I was doing, I think we are doing very different things.

  2. sacha says:

    mihailik

    I will download that Obtics stuff when I get a minute and have a play see what I think

  3. Mike Strobel says:

    +1 for Obtics. Aside from building observable objects and sequences, it’s a pretty nice framework for performing other kinds of transforms.

  4. sacha says:

    I’ll have to take Obtics for a ride

  5. Siderite says:

    It would seem to me that this goes well together with your templating and AOP efforts for INPC. I mean, if you don’t have to rewrite the code for INPC properties yourself, you can make it arbitrarily complex. In that case you could hook/unhook stuff on values that are implementing INPC or ObservableCollection or BindingList and still respect the law of Demeter.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: