We're very pleased to announce the release of the PostSharp Domain Toolkit – the first tool to treat the implementation of INotifyPropertyChanged seriously and finally end change notifications pain for WPF developers!

Let's start from the beginning...

The Problem

When you work with WPF using patterns such as Model-View-ViewModel (MVVM) or, in fact, any kind of data binding to your domain classes, in most cases you need to implement property values change notifications for your mutable objects. The .NET framework provides you with INotifyPropertyChanged interface but sadly leaves you the burden of implementing it. If you try to manually implement the interface, you'll end up with classes which look like this:

public class Customer : INotifyPropertyChanged
{
    private string firstName;
    public string FirstName
    {
        get { return firstName; }
        set
        {
            firstName = value;
            OnPropertyChanged("FirstName");
            OnPropertyChanged("FullName");
        }
    }
 
    private string lastName;
    public string LastName
    {
        get { return lastName; }
        set
        {
            lastName = value;
            OnPropertyChanged("LastName");
            OnPropertyChanged("FullName");
        }
    }

    public string FullName
    {
        get { return string.Concat(firstName, " ", lastName); }
    }

 
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

There are at least two problems here. First, notice the amount of boilerplate code in the solution. Instead of using simple automatic properties (one line of code), you need to create regular field-backed properties with OnPropertyChanged calls in each of them. Each property must also be aware of all other properties depending on its value (and we're still ignoring any inter-object dependencies).

What's worse, the code is now riddled with string literals. Just a minor typo is enough for the notifications to silently fail (with no build-time error and no runtime exception). Refactoring also becomes much harder – whenever you change the name of the property, you need to change the literal as well. Some refactoring tools might help here, but once you have several classes with the same property name (and you are going to have Name and Description properties on multiple classes) you can't fully trust them anymore.

If writing all this boilerplate code seems tiresome to you, think about tedium involved in debugging all the subtle problems that are so easily introduced by making a single typo or forgetting about a single dependency. Oh, the humanity!

Existing (Non-)Solutions

The problem is obviously not new and there are several libraries attempting to tackle it. Some of them would require you to create proxies or wrapper classes around your objects, introducing another layer of indirection and code complexity. Others simply make your boilerplate code less error-prone. In C# 5 (or using ActiveSharp in pre .NET 4.5 environment; see here and here for details) writing basic properties can be simplified to repeating a pattern similar to this one:

private int foo;
public int Foo
{
    get { return foo; }
    set { SetValue(ref foo, value); }
}

The more advanced solutions use IL weaving to automatically introduce property change notifications without actually requiring you to write any dedicated code. They can also handle basic properties dependencies supporting usage scenarios such as the one in this code snippet:

public class Person : INotifyPropertyChanged
{
    public string GivenNames { get; set; }
    public string FamilyName { get; set; }

    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }   //...
}

Real Life

As usual, limitations and problems become obvious when you start using those solutions in real life. While they may handle the easy scenarios easily, it turns out that what you actually want to write in your code is not always that simple.

First, you may have various reasons to set field values directly and not via property setters. You may not even have properties for some of the fields at all:

private string firstName;
private string lastName;

public string Name
{
    get { return string.Concat(firstName, " ", lastName); }
}

The problem here is that none of the previously available solutions are able to automatically react to field values changes.

Second, when creating MVVM applications you will often want to have properties depending on values of child objects’ properties:

private Customer customer;

public string CustomerName
{
    get { return string.Concat(this.customer.FirstName,
                               " ", this.customer.LastName); }
}

How do you raise change notifications for the CustomerName property in this case?

You could try listening to NotifyPropertyChanged events of the Customer object, but you would have to manually write code to properly add and remove the necessary event handlers. Imagine how complicated and error-prone it would get with multi-level dependencies:

public string CustomerCity
{
   get { return this.customer.Address.City; }
}

 

Enter PostSharp Domain Toolkit.

PostSharp Domain Toolkit

Having personally experienced all the above pain points, and having at our disposal all the power of PostSharp, we decided to finally tackle the problem of property change notifications for (nearly) all standard business cases.

While simple PostSharp-based INotifyPropertyChanged implementations have long been available (see, for example, here), we decided to take the problem more seriously and made sure we concentrated on useful cases rather than just the easy ones.

The Domain Toolkit properly supports all of the above cases while also providing API and customization points for even more sophisticated scenarios. It automatically handles the following:

  • automatic and field-backed properties;
  • complex properties directly or indirectly depending on fields and other properties of the same class;
  • complex properties depending on methods within the same class (as long as they do not depend on methods in other classes);
  • complex properties depending on properties of child objects providing change notifications (automatically in case of simple property chains, basing on explicit declaration of dependencies in case of arbitrarily complex code).

To better understand the power of PostSharp Domain Toolkit simply have a look at the code below:

[NotifyPropertyChanged]
class CustomerViewModel
{
    private Customer customer;
 
    public CustomerViewModel(Customer customer)
    {
        this.customer = customer;
    }
 
    public string FirstName
    {
        get { return this.customer.FirstName; }
        set { this.customer.FirstName = value; }
    }
 
    public string LastName
    {
        get { return this.customer.LastName; }
        set { this.customer.LastName = value; }
    }
 
    public Address Address { get { return this.customer.Address; } }
 
    public string FullName { get { return this.customer.FullName; } }
 
    public string BusinessCard
    {
        get
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(this.FirstName);
            stringBuilder.Append(" ");
            stringBuilder.Append(this.LastName);
            stringBuilder.AppendLine();
            stringBuilder.AppendLine(this.customer.Address.Line1);
            string line2 = this.customer.Address.Line2;
            if (!string.IsNullOrWhiteSpace(line2))
            {
               stringBuilder.AppendLine(line2);
            }
            stringBuilder.Append(this.customer.Address.PostalCode);
            stringBuilder.Append(' ');
            stringBuilder.Append(this.customer.Address.Town);
 
            return stringBuilder.ToString();
        }
    }
}

[NotifyPropertyChanged]
class Customer
{
    private string lastName;
    private Address address;
 
    public string FirstName { get; set; }
 
    public string LastName
    {
        get { return lastName; }
        set { lastName = value; }
    }
 
    public Address Address
    {
        get { return address; }
        set { address = value; }
    }
 
    public string FullName
    {
        get { return string.Join( " ", this.FirstName, this.LastName ); }
    }
 
    public void Reset()
    {
        this.FirstName = null;
        this.lastName = null;
        this.address = null;
    }
 
}

Yes, all the properties in the above classes are going to automatically raise change notifications, thanks to just the single NotifyPropertyChangedAttribute per class!

And that’s not all, our toolkit is the first framework that realizes you may not always want to raise change notification immediately after property value change. Consider this snippet:

public class Account
{
    public decimal Balance { get; private set; }
    public DateTime LastOperationTime { get; private set; }
    public int RemainingDailyOperationsLimit { get; private set; }
 
    //...

    public void Withdraw(decimal amount)
    {
        //... all kinds of checks ...

        this.LastOperationTime = DateTime.UtcNow;
        this.RemainingDailyOperationsLimit--;
        this.Balance -= amount;
    }
 
    //...
}

In all the solutions considered so far, this snippet would raise notification after each single property change, which means that at the time the first 2 of 3 events have been raised, the Account object would be in an inconsistent state, some property values would have already been modified and some not.

In this case your change notification listener would see an object in which the last operation time is already updated, but the account balance is lagging behind. This may not be a serious issue if all you need the notifications for is a simple case of displaying the values on-screen. It does get serious, however, as soon as any kind of business (or even more advanced presentation) code starts to react to the events.

The only consistent solution here is to raise all the events at the end of the method only. And that is exactly what our framework does. It intelligently identifies when execution flows back from an object to its caller, and only then, when the object state should again be consistent, raises all pending change notifications. All this, so there is nothing for you to worry about.

Summary

The automatic property change notifications mechanism in the new PostSharp Domain Toolkit automatically handles all standard business cases and generates exactly the right notifications, at exactly the right time.

Just like the other PostSharp Toolkits, the new Domain Toolkit frees you from spending precious time on infrastructural issues and keeps you focused on business logic.

As always, you can trust our solution not to misbehave or fail silently. If we encounter any code construct we can't properly handle automatically, we'll notify you about it by emitting an error at compile time. You'll then have a chance to use an additional attribute to help the Toolkit identify the property or method dependencies. Or, if you prefer, you can take even more control by using our public API to deal with your corner cases. But that's a topic for another blog post and honestly we don't expect you to need that possibility often (if ever).

More posts on Postsharp Domain Toolkit coming soon. In the meantime, you can have a look at the source of the PostSharp Domain Toolkit on github or, even better, install the nuget package and immediately start using the new framework (sample code above should be more than enough to get you started).

Happy PostSharping!

Karol Walędzik is an enterprise software applications architect and developer at Internetium Sp. z o.o. (Warsaw, Poland), as well as a .NET Programming and Artificial Intelligence lecturer and AI researcher at Warsaw University of Technology.

Comments (11) -

Andreas
Andreas
8/15/2012 7:18:40 AM #

Hi,

Great toolkit. I just tested it and it works pretty well.
Happens that I was working on that problem recently too. So three comments from my side:

(Scenario: Model with one Property. Presenter forwards that property.)

- If I test the approach in that article, the event is raised twice for the dependent property.
Differences to the example in the article:
  * I'm implementing IModel and IPresenter. Both implement INotifyPropertyChanged.
  * Properties are all Auto-Properties (no backing fields)

- The biggest problem I encountered in my (automated) solutions so far are memory leaks due to the event subscriptions. How do you deal with them? Unsubscribe if set to null? Weak events if we don't know when to unsubscribe?

- A warning. The application I am working on has a lot of Models and Presenters (>100.000).
As I recently evaluated some approaches for exactly the problem in the article, I had a test suite in place and wanted to post my results here for the ppl who are dealing with the same amount of objects as we do.

Scenario: The Model Presenter objects as described above. Tests:
1) I create 100.000 Presenter/Model pairs and stop the time.
2) I set the property on the model of all 100.000 instances and stop the time how long it takes (events will be forwarded and raised by presenter).
3) I take a snapshot with ANTS Memory Profiler and see how much memory was allocated.

Results:
PostSharp Toolkit
1) 6079 ms
2) 7524 ms
3) 99.4 MB

Classic (the old school way. Strings and all those boiler plate code)
1) 37 ms
2) 5 ms
3) 6.5 MB

Just to compare. My own approach (uses expressions to automatically setup dependencies and eliminate strings for them. Regular OnProperyChanged("string") in properties on model though)
1) 52 ms
2) 10 ms
4) 8.5 MB

My Expressions approach for dependencies; Old PropertyChanged aspect to eliminate the strings in the properties too:
1) 304 ms
2) 212 ms
3) 21 MB


Of course the overhead in % wouldn't be that high if the objects would be more complex.
However, I think it is important to be aware of the overhead a broad usage of that aspect (and aspects in general) in an application with many objects might cause.

Hope that is helpful.

Cheers,
Andreas

Gael Fraiteur
Gael Fraiteur
8/16/2012 9:48:59 AM #

Hi Andreas,

Thank you for your comment.

I will let Karol investigate the issue with multiple change notifications.

Regarding the performance issue, it's clear that there's some overhead to pay for. I don't think this is an issue in scenarios where changes are caused by inputs of the current user, but there may be other cases where it could be an issue.

In this first release, we did not focus on performance. In theory, a lot could be done to improve performance, and we could even do better than hand-written code. In practice, it would be a significant investment and we would perhaps hit some limitations of PostSharp. We'll seek to improve this in some future release.

-gael

Karol Waledzik
Karol Waledzik
8/21/2012 3:13:10 PM #

Hi Andreas,

I tried to reproduce your problem with duplicate notifications, but I do not get the same behavior. Can you perhaps provide me with a repro?

As far as performance is considered, we know of several ways we can somewhat improve it, but we did want not invest much time in it yet. Still, we did some testing for scenarios we expected to be representative for typical usage of the toolkit and the overhead was relatively small.

Regarding your question about notifications and memory leaks: if you have a look at the source code on github, you'll notice that apart from standard INPC notifications we also introduce dedicated kind of event for propagation of changes between dependent objects. This way we're avoiding much of the complexity we would have relying directly on PropertyChanged.

Karol

Jordan
Jordan
8/22/2012 9:48:33 PM #

Would love to see how you override/manually emit INPC

Andreas
Andreas
8/23/2012 7:03:42 AM #

Hi again,

Time to answer the questions.

@Karol: I would be happy to send you the code, if you provide me with an email address. It would be slightly messy to put the code into this post. I didn't investigate the problem myself though as it wasn't important to me now. So it might be just a stupid mistake on my side.

@PostSharp team: I still use aspects in 60-70% of the situations and I woldn't want to miss it. But I learned, that in some scenarios the footprint in memory and performance is just to high. I think that's ok as I do not believe in a "one size fits all" solution anyway. There is always a trade of. However, it took me while to get to this conclusion and I wanted to share it :).

@Jordan: As I wrote before, my application deals with a huge amount of objects. So what I did is to introduce multiple options depending on the speed and memory footprint I am able to afford. I can outline them here and if you want some more information, just let me know. So I will name them from most speed / low memory to lowest speed / highest memory.
This methods all address the same INPC and forwarding the models NPC in the presenter.

1) Classic. I use this if speed is absolutely essential and I can not have any wasted memory:
This is the old method: [b]OnPropertyChanged("PropertyName")[/b]. Subscribing to models INPC and then Switch/Case incoming events to outgoing events.
[b]if (e.PropertyName.Equals("FirstName")) OnPropertyChanged("FullName"); [/b]
Something like that. => Horrible

2) I still use [b]OnPropertyChanged("PropertyName")[/b] in the setters, but the forwarding part is better :).
Instead of writing this whole [b]if (...) OnPropertyChanged()[/b],
I use a static method to define and compile an expression which represents exactly that.
It looks like this:

[b]private static readonly PropertyChangedMappings mappings =
  PropChangedMapper.CreateMappings<SourceClass, TargetClass>()
    .AddMapping(s => s.SourceProp, t => t.DependentProp)
    .AddMapping(s => s.SourceProp, t => t.SecondDependentProp)
    .FinalizeBuild();[/b]

* No strings. As I use expressions, I am free to actually use the properties.
* It is static. So the whole work is only done once and then reused throughout all instances.
* The method is compiled. Almost as fast as writing by hand ;)

Now we need to hook it up. To do so, we need to input to things:
- Hook it up to INPC of the model (source) (weak or hard suscription as you wish)
- Provide it with the OnPropertyChanged(string) methode on the presenter.

[b]source.PropertyChanged += (s, a) => mappings(a, OnPropertyChanged);[/b]

And thats it. The method will take the arguments, check the created mappings and raise the OnPropertyChanged method on the target.

This produces almost no overhead at all (see my initial post).

3) I use the old NotifyPropertyChanged aspect to eliminate the [b]OnPropertyChanged("PropertyName")[/b]. Because it basically only intercepts the setter, the overhead is not that big but still pretty significant (check first post the exact numbers again). The forwarding is still done with the method described before.

4) My own PropertyDependecies aspect or the one described in this article. Of course it is by far the most comfortable, but the price is pretty high. (Again, check the numbers in the first post)


If there is any interest in my expressions approach, please feel free to ask. I'll be happy to provide more infos (comment gets already pretty long ;).

Cheers,
Andreas

Matteo Migliore
Matteo Migliore
8/25/2012 10:58:31 AM #

Hi!

I've a problem with the implementation of IDataErrorInfo, I obtain this error from PS:
Error  1  NotifyPropertyChangedAttribute: automatic analysis of property Xxx.Item [System.String] failed. Method Xxx.get_Item(System.String) contains call to non void (ref/out param) method of another class.Use InstanceScopedProperty attribute to specify that property value depends only on state of current instance, DependsOn attribute to explicitly specify dependencies or mark called method with IdempotentMethodAttribute attribute to specify that the method is idempotent.

I don't find the InstanceScopedProperty attribute and, isn't possible to automatically ignore the Item property if the VM implements IDataErrorInfo?

Thanks!
Matteo.

Karol Waledzik
Karol Waledzik
8/27/2012 2:34:19 PM #

Hi Matteo,

I assume you are programming in VB (in C# IDataErrorInfo simply works). You should put NotifyPropertyChangedIgnoreAttribute on the Item property.

Also: the reference to InstanceScopedPropertyAttribute in the error message is invalid, it should point to NotifyPropertyChangedSafe. We will fix it in the next release, sorry for the confusion.

Hope this helps,

Karol

Karol Waledzik
Karol Waledzik
8/27/2012 2:37:52 PM #

Andreas,

could you please send me the repro to karol.waledzik - at - internetium.pl?

Thanks,
Karol

Matteo Migliore
Matteo Migliore
8/27/2012 3:25:52 PM #

I sent you the sample application that doesn't work.

I code with C# :).

Matteo.

Martin Laufer
Martin Laufer
9/2/2012 5:33:22 PM #

Hi,

thats great stuff. You did a very good job on implementing INotifyPropertyChanged. But some points are still open for me:
- will the toolkit handle circular property dependencies correctly? (even across several objects - the property circle may contain two or more objects)
- how are lambda bodies, that manipulate properties covered by notification, are handeled - just as plain method bodies? What about compiled expression trees?
- the toolkit will rise the notification event when the stack scope changes (as needed). This puts a limitation to the refactoring abilities of code, that mutates property values - all of the property changes have to occour inside one method body. One just can't refactor parts of the method body into another method - without introducing observable side effects. So there has to be some information about that to be documented - best putting a comment into the code (describing the side effect). BUT if one is obligued to place such a comment, then why not create a statement, that does eactly that - there comes TransactionScope to mind...

I've used for some time an intterface (ISupportUpdate) which mainly consists of two methods (BeginUpdate/EndUpdate). After invoking BeginUpdate, the object is supposed to be in an (at least partially) inconsistent state (which may rise Exceptions on some members). And with the help of extension methods on that interface I can cerate constructs like
using(someUpdateableObject.UpdateScope())
{
    // manipulate the state of the object here
    // which will not rise any events
}
// after the end of the UpdateScope any suppressed events should be rised
// preferrably by the dispose method of the scope...

With the help of that construction, the consistency scope of the object is very clear - and no comments needed to express the behaviour.

I would have liked such fuctionality in the toolkit.

Thanks, Martin

Karol Waledzik
Karol Waledzik
9/3/2012 2:43:19 PM #

Hi Martin,

* Yes, the toolkit is prepared for circular references and should handle them correctly.

* At the moment our automatic analysis does not support delegates. If it encounters one, it reports error and requests more explicit dependencies configuration. Expression trees, on the other hand, are handled in the same way as any other object.

* Simple 'introduce method' refactoring will not influence the notifications behavior and there will be no side effects. Events are only raised when the execution context moves between object instances, which would not be the case here.
Still, your API suggestion might be useful in some other cases and it is, in fact, one of the ideas in our backlog.

Karol

Pingbacks and trackbacks (2)+

Comments are closed