José F. Romaniello

Las aventuras y desventuras de un codificador.

How many times have you seen something like this?

public class Album : Entity, IAlbum
{
    public virtual Artist Artist { get;  set; }
    public virtual string Title { get; set; }

    public virtual IEnumerable<Track> Tracks { get; private set; }
    public virtual void AddTrack(Track track)
    {
        track.Album = this;
        Tracks.Add(track);
    }
    public virtual void AddTracks(IEnumerable<Track> tracks)
    {
        tracks.ForEach(AddTrack);
        
    }
    public Album()
    {
        Tracks = new List<Track>();
    }
}

The question is why is better than this:

public class Album : Entity, IAlbum
{
    public virtual Artist Artist { get;  set; }
    public virtual string Title { get; set; }

    public virtual ICollection<Track> Tracks { get; private set; }

    public Album()
    {
        Tracks = new EditableCollection<Track>();
        Tracks.CollectionChanged += (sender, args) =>
              {
                  if (args.Action == NotifyCollectionChangedAction.Add)
                      args.NewItems.ForEach(track => track.Album = this);
              };
    }
}

Then you can call album.Tracks.Add( .. ) normally. EditableCollection is from my previous post. You can do the same for the remove method.

| More

In the lasts lines of this post I talk about a Collection type that implements IEditableObject interface.
Let’s start with a simple interface:

public interface IEditableCollection<T> : 
IEnumerable<T>, IEditableObject, INotifyCollectionChanged {}

As you can see the interface also inherits INotifyCollectionChanged this is very usefull in data binding scenarios.
This is the implementation:

public class EditableCollection<T> : ObservableCollection<T>, IEditableCollection<T>
{
    private IList<T> _bakupList;
    private bool _isInEditMode;

    #region IEditableCollection Members

    public void BeginEdit()
    {
        _bakupList = new List<T>();
        Items.ForEach(_bakupList.Add);
        _isInEditMode = true;
    }

    public void EndEdit()
    {
        if (!_isInEditMode)
            throw new InvalidOperationException("EndEdit without a BeginEdit"); 
        _isInEditMode = false;
        _bakupList = null;
    }

    public void CancelEdit()
    {
        if(!_isInEditMode)
            throw new InvalidOperationException("CancelEdit without a BeginEdit"); 
        _isInEditMode = false;
        ClearItems();
        _bakupList.ForEach(Add);
        _bakupList = null;
    }

    #endregion
}

Some unit test to see what you can do:

[Test]
public void can_add_and_cancel()
{
    var editableList = new EditableCollection<string>
                           {
                               "a","b","c"
                           };
    
    editableList.BeginEdit();
    editableList.Add("f");
    editableList.CancelEdit();

    editableList.Should().Have.SameSequenceAs("a,b,c".Split(','));
    

}

[Test]
public void can_remove_and_cancel()
{
    var editableList = new EditableCollection<string>
                           {
                               "a","b","c"
                           };

    editableList.BeginEdit();
    editableList.Remove("c");
    editableList.CancelEdit();

    editableList.Should().Have.SameSequenceAs("a,b,c".Split(','));

}

[Test]
public void can_clear_and_cancel()
{
    var editableList = new EditableCollection<string>
                           {
                               "a","b","c"
                           };

    editableList.BeginEdit();
    editableList.Clear();
    editableList.CancelEdit();

    editableList.Should().Have.SameSequenceAs("a,b,c".Split(','));

}

This code is in uNhAddins.Wpf with the complete set of unit test. 

| More

ForEach method is wonderful, unfortunately is a member of List<T>.
What if you want to have this method in all IEnumerable<T>? well, this extension method can help.

public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
    foreach (var item in collection){ action(item); }            
}

With this method you can do the following:

"a,b,c,d".Split(',').ForEach(Console.WriteLine);

Note: This article was titled “ForEach method in every ICollection<T>”, but as suggested by Fabio Maulo can be better with IEnumerable<T>, so I’ve downgraded the type of the parameter.

| More

I will show you in this post a simple mistake with LINQ.
Take a look to this inoffensive method:

public static IEnumerable<string> WithTwoChars(IEnumerable<string> list)
{
    return list.Where(s => s.Length.Equals(2));
}

It takes a collection of string and returns strings with two chars.

This code use the above method:

IEnumerable<string> result = WithTwoChars(SimpleWordList());
Console.WriteLine("Count is {0} ", result.Count());
Console.WriteLine("First item is {0} ", result.ToList()[0]);

But…. what is the difference between this one:

IEnumerable<string> result = WithTwohars(SimpleWordList()).ToList();
Console.WriteLine("Count is {0} ", result.Count());
Console.WriteLine("First item is {0} ", result[0]);

The difference is quite obviously the former method iterate over the coll twice. If you put a stopwatch you will notice the difference.

| More

I really like this interface, so I decided to dedicate a post to this beauty. As you can read in my previous post I am using dynamic proxy to apply this behavior dynamically.

Let me show you my love with some tests:

private const string title = "The dark side of the moon";
private const string newTitle = "Dark side of the moon";

[Test]
public void transient_entity_should_commitchanges_after_endedit()
{
    var album = container.Resolve<Album>();
    
    album.Title = title;

    ((IEditableObject)album).BeginEdit();
    album.Title = newTitle;
    ((IEditableObject)album).EndEdit();

    album.Title.Should().Be.EqualTo(newTitle);
}

[Test]
public void transient_entity_should_rollback_after_canceledit()
{
    var album = container.Resolve<Album>();

    album.Title = title;

    ((IEditableObject)album).BeginEdit();
    album.Title = newTitle;
    ((IEditableObject)album).CancelEdit();

    album.Title.Should().Be.EqualTo(title);
}

Could we add this behavior to nhibernate entities? Yes, I’m working on uNhAddIns.WPF for that matter. But let me show you two simple test:

[Test]
public void session_should_be_dirty_after_commitchanges()
{
    var id = CreateNewAlbum();
    using (ISession session = sessions.OpenSession())
    using (ITransaction tx = session.BeginTransaction())
    {
        var album = session.Get<Album>(id);
        ((IEditableObject)album).BeginEdit();
        album.Title = "Dark side of the moon";
        ((IEditableObject)album).EndEdit();

        session.IsDirty().Should().Be.True();

        tx.Commit();
    }
}

[Test]
public void session_shouldnot_be_dirty_after_cancelchanges()
{
    var id = CreateNewAlbum();
    using (ISession session = sessions.OpenSession())
    using (ITransaction tx = session.BeginTransaction())
    {
        var album = session.Get<Album>(id);
        ((IEditableObject)album).BeginEdit();
        album.Title = "Dark side of the moon";
        ((IEditableObject)album).CancelEdit();

        session.IsDirty().Should().Be.False();

        tx.Commit();
    }
}

As you can see when we cancel the edition the entity restore his values and the current session should not be dirty.

What do you think about this one?

    var id = CreateNewAlbum();
    using (ISession session = sessions.OpenSession())
    using (ITransaction tx = session.BeginTransaction())
    {
        var album = session.Get<Album>(id);
        ((IEditableObject)album).BeginEdit();
        album.AddTrack(new Track("On the Run"));
        ((IEditableObject)album).CancelEdit();

        album.Tracks.Any(t => t.Name == "On the Run")
                    .Should().Be.False();

        session.IsDirty().Should().Be.False();

        tx.Commit();
    }

Well this is not yet implemented, but CancelEdit will raise cancel’s within the full object graph. In this case Tracks use a collection type that implements IEditableObject.

I mix this concept whit CpBT (from uNhAddIns) and I did manage to resolve an interface like this with a few  databindings.

 window

Thoughts?

| More

If you were reading my previous posts you will notice that I am injecting entities in my IoC. This way the container can inject services in your entities. The other reason to inject entities in your container is when you container integrates very well with a proxy generator (as you can read in my examples of AOP).

The problem is entities are not injectable, the container should inject services in entities but not entities in services nor entities in entities.

So, this is my code snippet for Windsor Container.
The facility:

public class NonInjectableFacility : AbstractFacility
{
    public const string NonInjectablePropertyKey = "noninjectable";

    private readonly ArrayList _nonInjectables = new ArrayList();

    private void Kernel_ComponentModelCreated(ComponentModel model)
    {
        if (model.ExtendedProperties.Contains(ExtendWithPropertyKey))
        {
            _nonInjectables.Add(model.Service);
            foreach (ComponentModel componentModel in Kernel.GraphNodes.OfType<ComponentModel>())
                RemoveNonInjectables(componentModel);
        }
        RemoveNonInjectables(model);
    }

    private void RemoveNonInjectables(ComponentModel model)
    {
        List<PropertySet> propertiesToRemove = model.Properties
            .Where(p => _nonInjectables.Contains(p.Property.PropertyType))
            .ToList();

        foreach (PropertySet propToRemove in propertiesToRemove)
            model.Properties.Remove(propToRemove);
    }

    protected override void Init()
    {
        Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;
    }
}

A registration extension:

public static class FluentRegister
{
    public static ComponentRegistration<T> NonInjectable<T>(
this ComponentRegistration<T> registration) { registration.ExtendedProperties(
Property.ForKey(NonInjectableFacility.NonInjectablePropertyKey).Eq(true)); return registration; } }

And the test:

[Test]
public void should_work()
{
    var c = new WindsorContainer();
    c.AddFacility<NonInjectableFacility>();

    c.Register(Component.For<IInjectableService>()
                   .ImplementedBy<InjectableService>());

    c.Register(Component.For<Service>());

    c.Register(Component.For<ITopMostService>()
                   .ImplementedBy<TopMost>().NonInjectable());

    c.Resolve<Service>().TopMostService.Should().Be.Null();
}

Note: Windsor has an attribute called [DoNotWire].

I took some ideas from Mauricio Scheffer’s answer in this thread and also I’ve stolen others ideas from this post of Tuna Toksoz.

| More


I will post here a little description of the concepts that I want to cover in the uNhAddins.Wpf component.

Please leave a comment here or in the mailing list with any feature that you will like to have in this package.

| More

I have been working over the last three weeks on a project with WPF. You can see my last four post about the subject:

This time I will go with the INotifyCollectionChanged interface. 
Given the following domain:

public class Store : IStore
{ public virtual string Name { get; set; } [NotifyOnChange] public virtual IList<IProduct> Products { get; private set; } public Store() { Products = new List<IProduct>(); } public virtual void AddProduct(IProduct product) { product.Store = this; Products.Add(product); } public virtual void RemoveProduct(IProduct product) { product.Store = null; Products.Remove(product); } }

Note: NotifyOnChangeAttribute is mine. 
The mapping:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="uNHAddIns.Examples.CustomInterceptor"
                   namespace="uNHAddIns.Examples.CustomInterceptor.Domain">
  <class name="Store" >

    <id type="guid">
            <generator class="guid"/>
        </id>
    
        <property name="Name"/>
    
    <bag name="Products" cascade="all" inverse="true">
      <key column="StoreId" />
      <one-to-many class="IProduct" />
    </bag>
    
    </class>
</hibernate-mapping>
We need to meet the following test:

[Test]
public void NotifyOnChangeProperty_Should_Implement_INotifyCollectionChanged()
{
    var store = container.Resolve<IStore>();
    typeof(INotifyCollectionChanged).IsAssignableFrom(store.Products.GetType());
    typeof(INotifyPropertyChanged).IsAssignableFrom(store.Products.GetType());
}
[Test]
public void add_should_raise_collectionchanged()
{
    var store = container.Resolve<IStore>();
    IProduct newProduct = CreateNewProduct();
    bool eventWasRaised = false;

    ((INotifyCollectionChanged) store.Products)
        .CollectionChanged += (sender, args) =>
        {
            eventWasRaised = true;
            args.Action.Should().Be.EqualTo(NotifyCollectionChangedAction.Add);
            args.NewItems.Count.Should().Be.EqualTo(1);
            args.NewItems[0].Should().Be.EqualTo(newProduct);
        };


    store.AddProduct(newProduct);

    eventWasRaised.Should().Be.True();
}

I won't show you the full set of test for now.

Implementing the dynamicProxy interceptor:

public class CollectionPropertyInterceptor : IInterceptor
{

    private readonly IDictionary<string, object> _interceptedCollections
        = new Dictionary<string, object>();

    private object[] AttributeLookup(Type type, Type attribType, string propertyName) 
    {}

    #region IInterceptor Members

    public void Intercept(IInvocation invocation)
    {
        if (!invocation.MethodInvocationTarget.Name.StartsWith("get_"))
        {
            invocation.Proceed();
            return;
        }

        string propName = invocation.MethodInvocationTarget.Name.Substring(4);

        if (AttributeLookup(invocation.InvocationTarget.GetType(),
                            typeof (NotifyOnChangeAttribute),
                            propName).Length != 1)
        {
            invocation.Proceed();
            return;
        }


        object interceptedCollection;
        _interceptedCollections.TryGetValue(propName, out interceptedCollection);

        if (interceptedCollection != null)
        {
            invocation.ReturnValue = interceptedCollection;
        }
        else
        {
            invocation.Proceed();

            var itemType = invocation.ReturnValue.GetType()
                                     .GetGenericArguments()[0];

            var observableType = typeof (ObservableCollection<>)
                                        .MakeGenericType(itemType);

            object newInterceptedCollection = 
                Activator.CreateInstance(observableType, invocation.ReturnValue);

            invocation.ReturnValue = newInterceptedCollection;

            _interceptedCollections.Add(propName, newInterceptedCollection);
        }
    }

    #endregion
}
Ok, what I’m doing here? Let me explain, this interceptor intercept the “get_Products” method call, and enwrap the return type into an ObservableCollection. Then I store this collection in a dictionary for subsequent calls.

You need to register the Store entity as follows:

container.Register(Component.For<Store>()
                       .Interceptors(new InterceptorReference(
                           typeof (CollectionPropertyInterceptor))).Anywhere
                       .ImplementedBy<Store>()
                       .EnableNhibernateEntityCompatibility()
                       .LifeStyle.Transient);

container.Register(Component.For<IStore>()
                       .UsingFactoryMethod(kernel => kernel.Resolve<Store>())
                       .LifeStyle.Transient);
Using the EnhancedBytecode provider from unhaddins this test also works:

[Test]
public void add_should_raise_collectionchanged_on_nontrascient()
{
    var id = CreateFooStore();
    IProduct newProduct = CreateNewProduct();

    using (var session = sessions.OpenSession())
    using(session.BeginTransaction())
    {
        var store = session.Get<Store>(id);
        bool eventWasRaised = false;
        ((INotifyCollectionChanged)store.Products)
            .CollectionChanged += (sender, args) =>
                {
                    eventWasRaised = true;
                    
                    args.Action
                        .Should().Be.EqualTo(NotifyCollectionChangedAction.Add);
                    
                    args.NewItems.Count
                        .Should().Be.EqualTo(1);
                    
                    args.NewItems[0]
                        .Should().Be.EqualTo(newProduct);
                };


        store.AddProduct(newProduct);

        eventWasRaised.Should().Be.True();
    }

}

I'm going to merge these functions into one package with everything you need to work with wpf, nhibernate and the aforementioned interfaces. This package will be available at unhaddins.

| More

Recently Krzysztof Koźmic has committed a patch to the DynamicProxy trunk that allows me to do a new trick. 
I will show you in this post a beautiful way to add behaviour to your entities.

I start defining this simple domain:

public interface IProduct
{
    int Id { get; }
    string Name { get; set; }
    double UnitPrice { get; set; }
}

public class Product : IProduct
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double UnitPrice { get; set; }
}

public interface IEditableProduct : IProduct, INotifyPropertyChanged, IEditableObject
{}

Then I could generate a proxy as follows:

public IEditableProduct GenerateEditableModelOfProduct(Product product)
{
    var proxyGen = new ProxyGenerator();

    return (IEditableProduct)
        proxyGen.CreateInterfaceProxyWithTargetInterface(typeof (IProduct), 
                             new[] {typeof (IEditableProduct)},
                             product, 
                             new ProxyGenerationOptions(), 
                             new IInterceptor[]
                                 {
                                     new EditableObjectInterceptor(), 
                                     new PropertyChangeInterceptor()
                                 }
                             );

}
Let me improve it by adding generics:
public TEditableInterface 
    GenerateEditableModel<TEditableInterface, TDomainInterface>(TDomainInterface entity)
    where TEditableInterface : INotifyPropertyChanged, IEditableObject, TDomainInterface
{
    var proxyGen = new ProxyGenerator();

    return (TEditableInterface)
        proxyGen.CreateInterfaceProxyWithTargetInterface(typeof(TDomainInterface), 
                             new[] {typeof (TEditableInterface)},
                             entity, 
                             new ProxyGenerationOptions(), 
                             new IInterceptor[]
                                 {
                                     new EditableObjectInterceptor(), 
                                     new PropertyChangeInterceptor()
                                 }
                             );
}

Note: you can take EditableObjectInterceptor and PropertyChangeInterceptor from unhaddins.examples.
And now the test:

[Test]
public void TestEditableBehaviour()
{
    var product = new Product()
                      {
                          Name = "Potatoes"
                      };

    var editableProductModel = GenerateEditableModel<IEditableProduct, IProduct>(product);
    editableProductModel.Name.Should().Be.EqualTo("Potatoes");
    
    editableProductModel.BeginEdit();
    editableProductModel.Name = "Apple";
    editableProductModel.Name.Should().Be.EqualTo("Apple");
    editableProductModel.CancelEdit();

    editableProductModel.Name.Should().Be.EqualTo("Potatoes");

    editableProductModel.BeginEdit();
    editableProductModel.Name = "Succory";
    editableProductModel.Name.Should().Be.EqualTo("Succory");
    editableProductModel.EndEdit();

    editableProductModel.Name.Should().Be.EqualTo("Succory");
}
[Test]
public void TestNotificableBehaviour()
{
    var product = new Product()
    {
        Name = "Potatoes"
    };
    bool eventWasCalled = false; 
    
    var editableProductModel = GenerateEditableModel<IEditableProduct, IProduct>(product);
    editableProductModel.PropertyChanged += (sender, args) =>
                                                {
                                                    if (args.PropertyName == "Name")
                                                        eventWasCalled = true;
                                                };
    editableProductModel.UnitPrice = 2.2;

    eventWasCalled.Should().Be.False();
    
    editableProductModel.Name = "Succory";

    eventWasCalled.Should().Be.True();
}

If you read my two previous post you will find a way to work with NHibernate as follows:

Session.Get<IProduct>(1);
//or:
Session.Get<IEditableProduct>(1);

kick it on DotNetKicks.com

| More

I’ve started a project in WPF and I’m learning Caliburn. I really like the way it handle the presentations patterns.
In this post I will show you a way to implement a ModelFramework based model with castle DynamicProxy2.

You can see a basic implementation here (extracted from the Lob Sample for WPF):

If you write your model in this way, you have:
-Automatic INotifyPropertyChanged behaviour.
-Automatic IEditableObject behaviour.
-Automatic n - Undo/Redon behaviour.
-Validations.
-other things.

Note:
I've already implemented the first two features with a Castle IInterceptor’s and DynamicProxy.
I will like to achieve the same result without implementing anything.

This is the model:

public interface ICustomer
{
    string Name { get; set; }
    string Address { get; set; }
}

public interface IEditableCustomerModel : ICustomer, IModel
{}

Note: IModel is from Caliburn.ModelFramework.

The picture:

caliburn.modelframework

The ModelInterceptor class will intercept the properties invocation and use the getvalue and setvalues of the ModelBase target.

The ModelHelper class generates the proxy as follows:

IEditableCustomerModel customerModel = 
    ModelHelper.CreateModel<IEditableCustomerModel, ICustomer>();







This test is working properly:
[Test]
public void can_undo_simple_property_change()
{
    var undoRedoManager = new UndoRedoManager();
    var customerModel = 
        ModelHelper.CreateModel<IEditableCustomerModel, ICustomer>();

    undoRedoManager.Register(customerModel);

    Assert.IsNotNull(customerModel);

    customerModel.Name = "Jose";
    
    customerModel.BeginEdit();

    //First I change the name to "Bill"
    customerModel.Name = "Bill";
    Assert.That(customerModel.Name, Is.EqualTo("Bill"));

    //Ups, No I say "Pedro".
    customerModel.Name = "Pedro";
    Assert.That(customerModel.Name, Is.EqualTo("Pedro"));

    //No, his name is "Andy".
    customerModel.Name = "Andy";
    Assert.That(customerModel.Name, Is.EqualTo("Andy"));


    //No, his name is bill so I will click undo twice.
    //One undo for pedro.
    undoRedoManager.Undo();
    Assert.That(customerModel.Name, Is.EqualTo("Pedro"));
    //Two undo for Bill
    undoRedoManager.Undo();
    Assert.That(customerModel.Name, Is.EqualTo("Bill"));


    //No... HIS NAME IS PEDRO!
    undoRedoManager.Redo();
    Assert.That(customerModel.Name, Is.EqualTo("Pedro"));

    customerModel.CancelEdit();

    Assert.That(customerModel.Name, Is.EqualTo("Jose"));
}

Importat Note: The implementation is working with the castle trunk R5846 thank you Krzysztof Koźmic!!
If you want the full code leave a comment with your email (or private) and I will send you.

kick it on DotNetKicks.com

| More

First of all you need to read my previous post and this from Fabio Maulo (a Italian guy who knows how to play truco better than me).
This time the behaviour is related to the IEditableObject. This interface has three methods BeginEdit, CancelEdit and EndEdit. Microsoft says:

Provides functionality to commit or rollback changes to an object that is used as a data source.

Note: it says “commit or rollback changes to an object”, not to a database.

Can we do it with a castle IInterceptor? YES.

The interceptor is defined as follows:

public class EditableObjectInterceptor : IInterceptor
   {
       private bool _isEditing;
       private readonly Dictionary<string, object> _propertyTempValues 
                                   = new Dictionary<string, object>();

       public void Intercept(IInvocation invocation)
       {
           switch (invocation.Method.Name)
           {
               case "BeginEdit":
                   _isEditing = true;
                   return;
               case "CancelEdit":
                   _isEditing = false;
                   return;
               case "EndEdit":
                   _isEditing = false;
                   AssignValues(invocation.InvocationTarget);
                   return;
           }
           if (!_isEditing)
           {
               invocation.Proceed();
               return;
           }
           if(!invocation.Method.Name.StartsWith("set_") 
               && !invocation.Method.Name.StartsWith("get_"))
               return;

           var isSet = invocation.Method.Name.StartsWith("set_");
           var propertyName = invocation.Method.Name.Substring(4);

           if(isSet)
           {
               _propertyTempValues[propertyName] = invocation.Arguments[0];
           }
           else
           {
               if (_propertyTempValues.ContainsKey(propertyName))
                   invocation.ReturnValue = _propertyTempValues[propertyName];
               else
                   invocation.Proceed();
           }
       }

       private void AssignValues(object target)
       {
           foreach (var propertyTempValue in _propertyTempValues)
           {
               var property = target.GetType().GetProperty(propertyTempValue.Key);
               property.SetValue(target, propertyTempValue.Value, null);
           }
       }
   }

If you use CommonDatastore (explained in my previous post) you add this behavior as follows:

container.Register(Component.For<IProduct>()
                            .AddEditableObjectBehavior()
                            .TargetIsCommonDatastore());

If you don’t use CommonDatastore:

container.Register(Component.For<Customer>()
                            .AddEditableObjectBehavior()
                            .EnableNhibernateEntityCompatibility());

Let the test speak for me:

        [Test]
        public void property_setters_should_work()
        {
            var product = container.Resolve<IProduct>();
            product.Description = "Potatoes";
            product.Description.Should().Be.EqualTo("Potatoes");

            product.BeginEdit();
            product.Description = "Banana";
            product.Description.Should().Be.EqualTo("Banana");
            product.Description = "Apple";
            product.Description.Should().Be.EqualTo("Apple");
            product.CancelEdit();
        }

        [Test]
        public void cancel_should_discard_changes_in_trascientobject()
        {
            var product = container.Resolve<IProduct>();
            product.Description = "Potatoes";
            product.Description.Should().Be.EqualTo("Potatoes");

            product.BeginEdit();
            product.Description = "Banana";
            product.Description.Should().Be.EqualTo("Banana");
            product.CancelEdit();

            product.Description.Should().Be.EqualTo("Potatoes");

        }

        [Test]
        public void endedit_should_push_changes_in_trascientobject()
        {
            var product = container.Resolve<IProduct>();
            product.Description = "Potatoes";
            product.Description.Should().Be.EqualTo("Potatoes");

            product.BeginEdit();
            product.Description = "Banana";
            product.EndEdit();

            product.Description.Should().Be.EqualTo("Banana");

        }

        [Test]
        public void cancel_should_discard_changes()
        {
            var id = CreatePotatoesProduct();
            using(var session = sessions.OpenSession())
            using(var tx = session.BeginTransaction())
            {
                var product = session.Get<IProduct>(id);

                product.Description.Should().Be.EqualTo("Potatoes");

                product.BeginEdit();
                product.Description = "Banana";
                product.Description.Should().Be.EqualTo("Banana");
                product.CancelEdit();

                product.Description.Should().Be.EqualTo("Potatoes");
            }
        }

        [Test]
        public void endedit_should_push_changes()
        {
            var id = CreatePotatoesProduct();
            using (var session = sessions.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                var product = session.Get<IProduct>(id);

                product.Description.Should().Be.EqualTo("Potatoes");

                product.BeginEdit();
                product.Description = "Banana";
                product.Description.Should().Be.EqualTo("Banana");
                product.EndEdit();
                product.Description.Should().Be.EqualTo("Banana");
            }
        }
kick it on DotNetKicks.com

| More

The purpose of this post is to demonstrate several ways to use INotifyPropertyChanged as an AOP aspect in your business entities. I will use DynamicProxy for AOP and NHibernate as orm mapper. Althought all methods can be plugged into nhibernate using tuplizer, I will skip this part until the final solution.

The Problem

Let’s say you have to implement INotifyPropertyChanged for several entities of your domain. This is an example of implementation:
public class Customer : INotifyPropertyChanged
   {
       public event PropertyChangedEventHandler PropertyChanged;

       protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
       {
           PropertyChangedEventHandler changed = PropertyChanged;
           if (changed != null) changed(this, e);
       }

       private string _name;
       public string Name
       {
           get { return _name; }
           set
           {
               _name = value;
               OnPropertyChanged(new PropertyChangedEventArgs("Name"));
           }
       }

       private string _address;
       public string Address
       {
           get { return _address; }
           set
           {
               _address = value;
               OnPropertyChanged(new PropertyChangedEventArgs("Address"));
           }
       }
   }

First way: proxy with concrete target

I will start with proxies right now. If you want to know more about dynamic proxy I suggest this link.
The big picture

first

The client api call “set_Name” on the proxy, the proxy forwards this call to the interceptor stack. The PropertyInterceptor “proceed and wait” this invocation to the concrete type. The operaton is completed in the concrete type and then the interceptor raise the PropertyChanged event to the client.
The domain entity is defined as follows:

public class Customer : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public string Name { get; set; }
    public string Address { get; set; }
}

Note: the event is never raised inside the concrete class.
My proxy could by generated this way:

var proxyGenerator = new ProxyGenerator();
proxyGenerator.CreateInterfaceProxyWithTarget(typeof (Customer), 
                                                            new Customer(), 
                                                            new PropertyInterceptor());

The class PropertyInterceptor is trivial so I wont talk about it for now.
It’s an horrible workaround and don’t worth it. Why? because you end up with some kind of partial class that doesn’t work as expected if you don’t hang the interceptor.
Let’s clarify it, if you see “Customer : INotifyPropertyChanged” and it has a suitable constructor, you can assume that this class will work well even without proxy, interceptor or any kind of initialization.

Second way: proxy with concrete target (not INotifyPropertyChanged)

Maybe you are thinking right now: why do not remove INotifyPropertyChanged and put this interface into the proxy. Because the proxy is automatically generated your client api will need to do something like this:

Customer customer; //= Get the customer from somewhere;
            var notificable = customer as INotifyPropertyChanged;
            if(notificable != null)
                notificable.PropertyChanged += //...

And again, this is an horrible workaround. What happens if notificable is null? somebody has removed the additional interface from the proxy.

Third way: enough is enough

GoF: Program to an interface, not an implementation. I like very much this interview.
Then… your interface could be implemented in many ways (¿or not implemented at all?).
I will start showing this interface:

public interface ICustomer : INotifyPropertyChanged
{
    string Name { get; set; }
    string Address { get; set; }
}

I can guarantee that if you hold an ICustomer instance somewhere, it will work as you expect.
Do I need to code twice, one for the interface and one for the concrete class? NO. If this were the case I would not be bothered to write this beautiful post.
You don’t need to code twice because you don’t need any concrete implementation of ICustomer. I know, you are more confused now.
Fabio Maulo wrote a great post. My first impression when I read it was “Fabio is insane”, the second impression was “Fabio is really insane”. Here I’m, with a good reason to let my entities to be “services” in terms of IoC.
The big picture:

third

The client api invokes set_Name and the proxy pass this call over the interceptor stack. The PropertyChangedInterceptor still behave as the first example. The second interceptor “DataStore” store the data in a Dictionary and doesn’t proceed with the invocation because there isn’t any target!
Despite the fact that there is not a real implementation of ICustomer, there is an implementation that dynamic proxy has generated for me. The profit of using this approach is that you really need just one interceptor or two for the whole domain. Let me guess: not all of your entities are POCO. Nor mine, so the point is that you can go with “abstract” (search the interview about this) and if you really really need a concrete implementation write it, but write his interface first.

My implementation

Last but not least, I let the container to generate the proxies when a consumer of ICustomer interface needs it. I managed to create an extension for the registration api in Windsor:

container.Register(Component.For<ICustomer>()
                            .NotifyOnPropertyChange()
                            .TargetIsCommonDatastore());

There are two different things, you could service with a concrete type and still use “NotifyOnPropertyChange”. If you use NotifyOnPropertyChange, the service must implement INotifyPropertyChanged.
For instance the consumer of the ICustomer could be an API that wants to create a new Customer in our system, or NHiberante. In NHibernate I just have to map the interface to the database.
On the other hand, NHibernate need to know how to create an instance of an ICustomer, “Tuplizer” and “IInstantiator” is the solution (as Fabio has mentioned in his blog).

/// <summary>
/// Resolve an entity through ServiceLocator.
/// This allow to inject a proxy and intercepted entity.
/// </summary>
public class ServiceLocatorInstantiator : IInstantiator
{
    #region IInstantiator Members

    private readonly Type _entityType;

    public ServiceLocatorInstantiator(Type entityType)
    {
        _entityType = entityType;
    }

    public object Instantiate(object id)
    {
        var obj = ServiceLocator.Current.GetInstance(_entityType);
        return obj;
    }

    public object Instantiate()
    {
        return Instantiate(null);
    }

    public bool IsInstance(object obj)
    {
        return _entityType.IsInstanceOfType(obj);
    }

    #endregion
}

Fabio’s instantiator and mine have the same aim. The main difference is that my IInstantiator uses a ServiceLocator while the other uses DynamicProxy directly.
The sample project is in unhaddins.
I hope you enjoy this history as I did.

kick it on DotNetKicks.com

| More