Continuing from the previous post on INotifyPropertyChanged and the PostSharp Domain Toolkit, it’s now time to satisfy curiosities and share some details on how the framework works, what its limitations are and how to overcome them by using available customization.

What the Domain Toolkit Does

If you looked closely at the sample classes in the previous blog post, you probably noticed they did not actually implement INotifyPropertyChanged interface, yet WPF still received the notifications.

How is that possible?

Our NotifyPropertyChangedAttribute simply introduces the interface during compilation. This is a very convenient approach in many cases, especially if you don’t need to listen for the notifications yourself.

In cases where you want to implement the interface explicitly or inherit from a class that already has the interface, the toolkit will expect you to implement an OnPropertyChanged(string) method raising the PropertyChanged event, because it’s impossible in .NET world to externally raise an object’s event.

[NotifyPropertyChanged]
class Entity : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

    //...
} 

When the Domain Toolkit Does It

In the previous post I mentioned that one of the features that distinguish our solution from the competition is the ability to automatically raise notifications only at the points in time in which objects are expected to be consistent.

Recall 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;
    }
 
    //...
}

Here you probably want to raise the change notifications when the full withdrawal operation has been completed and not after each property change. Our algorithm here assumes that whenever control returns from an object’s method to its caller in another object the executing instance (as well as all other objects modified by the method) should be in a consistent state. The toolkit at this point will raise notifications for all modified properties except those belonging to other objects currently higher in the stack trace (these objects may still be inconsistent).

Additionally, it tracks changes separately for each executing thread and always raises notifications on the thread whose actions resulted in the property value change.

How the Domain Toolkit Works

You may have figured out by now that our solution relies heavily on static compile-time analysis of the code of your property getters (and all other code they invoke directly or indirectly). This allows us to build a dependency map of all the fields and properties of the instrumented classes, which is then used during runtime for notifications generation.

Obviously, while this process is very powerful it also has its limitations. Since we perform static analysis only, there are some code constructs we cannot understand fully and automatically. We can still be ready to deal with some of those cases but from time to time we will need your help. Fortunately, we put strong emphasis on early detection of any and all unsupported scenarios and warn you about them with build-time errors (accompanied by advice on how to fix the problem).

Let’s have a look at exactly what is supported and what isn’t.

Automatically Supported Scenarios

As you have seen in the previous post, there is a good chance we can handle your full code base automatically. Here is a short summary of the scenarios we support:

  • Automatic properties:
public string FirstName { get; set; }
  • Field-backed properties:
private string lastName;

public string LastName
{
    get { return this.lastName; }
    set { this.lastName = value; }
}
  • Properties depending on multiple fields:
private string firstName;
private string lastName;

public string FullName
{
    get { return string.Join(" ", this.firstName, this.lastName); }
}
  • Properties depending on other properties of the same object:
public string FirstName { get; set; }
public string LastName { get; set; }

public string FullName
{
    get { return string.Join(" ", this.FirstName, this.LastName); }
}
  • Properties depending (directly or indirectly) on methods within the same class:
public string FullName { get { return this.GetFullName(); } }

public string GetFullName()
{
    return string.Join(" ", this.FirstName, this.LastName);
}
  • Properties depending on chains of invocations of properties of other instrumented classes:
public string CustomerCity
{
   get { return this.customer.Address.City; }
}
  • Properties depending on some well-known and static .NET framework methods with no hidden dependencies, as well as any void methods with no ref or out parameters:
public string GetFullName()
{
    return string.Join(" ", this.FirstName, this.LastName);
}
  • Any combination of the above cases, including recursive dependencies on properties and methods fulfilling above criteria

Limitations

You can probably use the above list to find the missing scenarios and work out library limitations but here’s a quick round-up of the most important ones in the current version of the framework:

  • Property getters depending on methods on other objects (except cases mentioned above)
  • Dependencies on external objects’ properties more complex than property getters invocation chains mentioned above
  • Properties depending on virtual methods
  • Direct or indirect usage of delegates in property getters
  • Dependencies on static fields
  • Properties depending on items in collections

As I mentioned before, all of these cases are detected at build-time and generate compile errors, at the same time advising you on possible workarounds.

The good news is we also provide you with a handy set of tools and APIs to effectively deal with the cases above if you should ever encounter them. Let’s have a look at them, starting with the simplest ones.

Manual Overrides

Should you decide you don’t need automatic change notifications for a single property in an otherwise instrumented class, be it the property never changes, or you know you’ll never bind to it, or that you simply want to raise the events manually, we provide you with that option. Simply mark the property with NotifyPropertyChangedIgnoreAttribute:

[NotifyPropertyChangedIgnore]
public string FullName { get { return this.GetFullName(); } }

If, in some scenarios, you feel that our toolkit plays it a bit too safe, e.g. reporting errors about unsupported code constructs in your property getter when in reality those non-analyzable snippets have no influence on the property value , you can ignore the errors by using NotifyPropertyChangedSafeAttribute:

[NotifyPropertyChangedSafe]
public string FullName
{
    get
    {
        this.logger.Log( "FullName property getter on {0}", this );
        return this.GetFullName();
    }
}

Let’s say you want to skip the analysis phase completely and simply define what your property depends on. Our framework supports dependencies on fields of the same class and properties of other instrumented classes. You can also construct dependencies as chains of such properties. All you need to do is put a snippet of code at the beginning of your property getter:

public string BusinessCard
{
    get
    {
       if (Depends.Guard)
       {
          Depends.On(this.FirstName, this.LastName,
                      customer.Address.Line1, customer.Address.Line2);
       }

       //…
    }
}

The Depends.Guard statement always evaluates to false, so that Depends.On() method is never actually executed and has no performance impact. We treat the necessity of using the if (Depends.Guard ) statement as a temporary solution and plan to get rid of it completely in a future release (allowing you to write single Depends.On() statements with no performance impact).

Still, the current syntax is already fully IntelliSense and refactoring friendly and these were our most important design goals for this iteration.

Idempotent Methods

In some cases you may know more about a method than our static analyzer can infer. You may know for instance that a particular method’s output value depends only on its arguments, or that any other dependencies it has can be safely treated as read-only. In such cases it’s not necessary for the toolkit to analyze the method nor does it matter if it violates some of the constraints.

We call such methods idempotent.

We introduced a special attribute called IdempotentMethodAttribute, which you can apply to a method to let the toolkit know that it can be safely ignored by the analyzer as long as only intrinsic types are passed as its arguments (in any other case the method’s return value could depend on arbitrary fields and properties of the passed objects).

That’s not to say that our library doesn’t know about some idempotent methods. If you have a look at the examples in this post and the previous one, you’ll notice that the toolkit automatically ignores calls to many .NET framework methods, such as string.Format(), string.Concat() or any usage of StringBuilder.

The algorithm assumes all static framework methods to be idempotent as long as only intrinsic type values are passed to them. Additionally, our solution also understands some of the often-used methods and classes, including the previously mentioned StringBuilder as well ToString() or GetHashCode().

Runtime Manipulations

Finally, for those of you who want to take full control and force the toolkit to raise events exactly when you need them, simply use static utility class NotifyPropertyChangedControllerand to perform one of several actions:

  • immediately raise events for all modified properties (except objects higher in the stack trace, which may be in an inconsistent state);
  • immediately raise events for all modified properties of a given object;
  • immediately raise notification for a specific property on a specific object (no matter whether the toolkit thinks it was modified or not).

Summary

All in all, our Domain Toolkit works “automagically” by default, giving you a INotifyPropertyChanged package that solves most of your needs, while also letting you take full control to tweak its behavior to meet all your needs. So grab the nuget package or download the source code from github, try it out and let us know what you think. We are, as always, open to your suggestions.

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.

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.