Dmitry Shechtman's Blog

December 19, 2009

IDataErrorInfo with Validation Application Block and Unity Interception AOP

Filed under: PropertyChange — Tags: , , , , , , , , , , , , — Dmitry Shechtman @ 12:40

This is the second article in a planned series of articles concerning AOP with Unity Interception and Policy Injection:

  1. INotifyPropertyChanged AOP
  2. IDataErrorInfo AOP
  3. Policy Injection
  4. Performance and optimizations
  5. The final solution

I hope you will find this useful in your work; all feedback will be greatly appreciated.

The previous article discussed an implementation of the INotifyPropertyChanged aspect using Unity Interception AOP. Today we will see how a similar approach can be applied to another interface commonly used by WPF (as well as by ASP.NET MVC).

The IDataErrorInfo interface consists of two methods:

  1. an indexer accepting a property name (columnName) parameter and
  2. an Error property.

We will solely focus on the indexer, which returns error messages on a per-property basis.

The Validation Application Block allows developers to easily incorporate input validation via property attributes and/or application configuration, supporting a variety of provided validators, as well as custom ones.

IDataErrorInfo and VAB seem to be a perfect match, and have indeed been integrated. Adding Unity Interception will further simplify input validation, so that (presentation) models could be specified in the following manner:

[NotifyPropertyChanged, DataErrorInfo]
public class Contact : MarshalByRefObject, INotifyPropertyChanged, IDataErrorInfo
{
    [StringLengthValidator(1, 20, MessageTemplate = "First name length must be between {3} and {5}.")]
    [ContainsCharactersValidator("0123456789", Negated = true, MessageTemplate = "First name cannot contain digits")]
    public string FirstName { get; set; }

    [StringLengthValidator(1, 20, MessageTemplate = "Last name length must be between {3} and {5}.")]
    [ContainsCharactersValidator("0123456789", Negated = true, MessageTemplate = "Last name cannot contain digits.")]
    public string LastName { get; set; }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public string Error
    {
        get { return null; }
    }

    public string this[string columnName]
    {
        get { return null; }
    }
}

Note: The implementation presented below is limited to classes derived (possibly indirectly) from MarshalByRefObject.

(more…)

December 12, 2009

INotifyPropertyChanged with Unity Interception AOP

Background

If you have ever developed a non-trivial application in WPF, you’ll probably find this familiar:

    public class ProductFamilyViewModel : INotifyPropertyChanged
    {
        private bool isSelected;
        public bool IsSelected
        {
            get { return isSelected; }
            set
            {
                if (isSelected != value)
                {
                    isSelected = value;
                    SendPropertyChanged("IsSelected");
                }
            }
        }

        private bool isExpanded;
        public bool IsExpanded
        {
            get { return isExpanded; }
            set
            {
                if (isExpanded != value)
                {
                    isExpanded = value;
                    SendPropertyChanged("IsExpanded");
                }
            }
        }

        private bool isActive;
        public bool IsActive
        {
            get { return isActive; }
            set
            {
                if (isActive != value)
                {
                    isActive = value;
                    SendPropertyChanged("IsActive");
                }
            }
        }

        private void SendPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

(This is an excerpt from a real class I’ve been working on; the actual code is bigger and uglier.)

Isn’t it sad that you have auto-implemented properties, but not the ability to use them? Wouldn’t you love to be able to do something like that?

[NotifyPropertyChanged]
public class ProductFamilyViewModel : MarshalByRefObject, INotifyPropertyChanged
{
    public bool IsSelected { get; set; }
    public bool IsExpanded { get; set; }
    public bool IsActive { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
}

This has been achieved (with varying levels of success) with DynamicProxy2 and repeatedly with PostSharp (reportedly refined in PostSharp 2.0), but what about Microsoft Enterprise Library?

At first, the Policy Injection Application Block might look like the perfect tool for the task, but looks are often deceiving; quoting Richard Banks:

Windsor and PIAB both have a shortfall that we can’t overcome.  Neither of them can alter the type of a class they are providing aspects for – they simply provide proxies that add hooks to intercept method calls.  We would still need to implement INotifyPropertyChanged in our class for binding to work.

Not to fret! Luckily, Enterprise Library 4.1 ships with the Unity Application Block (also available as a separate download). Unity, in turn, contains the mighty Interception Extension, which seems to be getting undeservedly little attention from developers. I guess this has to do with its poor documentation and lack of UI configuration support (expected to be added in 5.0).

None of these, however, have prevented Derek Greer from trying. His post contains a great introduction to Unity Interception (Prolegomena is definitely recommended) and quite a few insights, but sadly falls short of achieving the ultimate goal.

This article details a complete user-friendly implementation of the INotifyPropertyChanged aspect using Unity Interception AOP. It is the first in a planned series of articles concerning AOP with Unity Interception and Policy Injection:

  1. INotifyPropertyChanged AOP
  2. IDataErrorInfo AOP
  3. Policy Injection
  4. Performance and optimizations
  5. The final solution

I hope you will find this useful in your work; all feedback will be greatly appreciated.

Note: The implementation presented below is limited to classes derived (possibly indirectly) from MarshalByRefObject.

Update 2009-12-14: Dima Gershman, a truly knowledgeable colleague of mine, says go with the looks. Policy Injection wraps user objects with Interception’s transparent proxies, relieving us of the burden of manual configuration (and even improving performance!), although that comes at the price of some extra library dependencies. To be continued…

(more…)

Create a free website or blog at WordPress.com.