Showing posts with label AOP. Show all posts
Showing posts with label AOP. Show all posts

Last week Fredrik Normén had a couple of nice posts on argument validation using C# extension methods. It got me thinking on a different approach where a method interceptor could handle the validation.

First a short recap on argument validation. I guess everyone have seen or written code with some kind of argument validation, like this for example:

public void Add(string value)
{
  if (string.IsNullOrEmpty(value)) 
      throw new ArgumentException("The value can't be null or empty", "value");
    
  ///...
}

To make argument validation easier I have (to a small extent) used a modified version of this design by contract utility class. This utility class lets you write argument validation like this:

public void Add(string value)
{
  Check.Require(value != null, "value should not be null");
    
  ///...
  
  Check.Ensure(Count > 0);
}

So this got me thinking on how you could handle argument validation using method interception. With a method interceptor you could inspect the function arguments checking for validation attributes. I envisioned code looking like this: 

[Ensure(() => this.Count > 0)]
public void Register([NotNull] string name, [InRange(5,10)] int value)
{
  ///...
}

Getting the ensure post condition to work like that will be impossible since you can only use constant expressions in attribute constructors. This is something I think they should look at for C# 4.0, being able to define lambdas in attribute arguments would make interesting scenarios possible (like this). The NotNull and InRange attributes were very simple to implement: 

public abstract class ArgumentValidationAttribute : Attribute
{        
  public abstract void Validate(object value, string argumentName);
}

[AttributeUsage(AttributeTargets.Parameter)]
public class NotNullAttribute : ArgumentValidationAttribute
{
  public override void Validate(object value, string argumentName)
  {
    if (value == null)
    {
        throw new ArgumentNullException(argumentName);
    }
  }    
}    

[AttributeUsage(AttributeTargets.Parameter)]
public class InRangeAttribute : ArgumentValidationAttribute
{
  private int min;
  private int max;

  public InRangeAttribute(int min, int max)
  {
    this.min = min;
    this.max = max;
  }

  public override void Validate(object value, string argumentName)
  {
    int intValue = (int)value;
    if (intValue < min || intValue > max)
    {
      throw new ArgumentOutOfRangeException(argumentName, string.Format("min={0}, max={1}", min, max));
    }
  }
}

This is of course the easy part. It is the actual interceptor that is making the magic happen. This implementation is just a proof of concept, and not optimal from a performance stand point.

public class ValidationInterceptor : IInterceptor
{
  public void Intercept(IInvocation invocation)
  {
    ParameterInfo[] parameters = invocation.Method.GetParameters(); 
    for (int index = 0; index < parameters.Length; index++)
    {
      var paramInfo = parameters[index];
      var attributes = paramInfo.GetCustomAttributes(typeof(ArgumentValidationAttribute), false);

      if (attributes.Length == 0)
        continue;

      foreach (ArgumentValidationAttribute attr in attributes)
      {    
        attr.Validate(invocation.Arguments[index], paramInfo.Name);
      }            
    }

    invocation.Proceed();
  }        
}

To make this interceptor more feasible for production you would probably have to add some smart caching mechanism. This interceptor based argument validation is of course somewhat limited in applicability. You have to use a dynamic proxy generator to get the interceptor functionality and only interface and virtual functions can be intercepted. But it is an interesting idea and shows another nice usage scenario for method interception.

The concept of being able to intercept method calls is something that would be great if it was built into a future version of the CLR runtime. That way static and non virtual methods could be intercepted. It is a nice way to implement cross-cutting concerns (like validation). But until then we will have to live with proxy generators, it works nicely for interfaces:

public interface IRegistrationService
{
  void Register([NotNull] string name, [InRange(5, 10)] int value);

  void Register([NotNullOrEmpty] string name);
}

If you specify the attributes on an interface you do not need to duplicate them on the implementation methods! A small update to the interceptor to support validation of the return value would allow something like this:

public interface IUserRepository
{
  [return: NotNull]
  User GetById([GreaterThanZero] int id);
  
  ///...
}

The syntax for attributes on return values are kind of funky. If Spec# isn't the future (I hope it is) then maybe something like this can be :)

I have been working on a WPF application lately and today I came across a rather common scenario where I needed to do stuff in a background thread (in order to not lock the UI). In this scenario I needed to do indexing, during the indexing I want the UI to be updated with progress (what file is being index, how many has been indexed, etc). I handled this by having the indexing service expose some progress events that the UI could subscribe to, like this:

private void OnStartIndexing()
{
    var indexer = new FileIndexer();
    indexer.IndexingFile += IndexingFileCallback;
    indexer.IndexingCompleted += IndexingCompletedCallback;
    indexer.SavingIndexStarted += IndexerSavingIndexStarted;

    ThreadPool.QueueUserWorkItem(x => { indexer.Run(); });
}

protected void IndexingCompletedCallback()
{
    View.HideInfoText();
}

The problem here is that the function IndexingCompletedCallback is not being called in the UI thread and will throw an exception. To solve this you have to use the Dispatcher like this:

Action action = delegate()
{
    Views.HideInfo();
};
Dispatcher.BeginInvoke(DispatcherPriority.Normal, action);

When I saw this I thought that this could be handled in a more general declarative way by using function attributes and AOP. So I tried to get this to work:

[UseDispatcher]
protected virtual void IndexingCompletedCallback()
{
    View.HideInfoText();
}

The fun part was that it was very easy to do, since I already used Castle Windsor for my presenters it was just a matter of configuring my base presenter class with an interceptor and in the interceptor it was just a matter of calling the invocation.Proceed() in a delegate passed to the Dispatcher.

Just for completeness here is the code for the base presenter:
[Interceptor(typeof(PresenterInterceptor))]
public abstract class Presenter<T>
{
    public T View { get; private set; }
    
    public void Wireup(T view)
    {
        View = view;
        Initialize();
    }

    protected abstract void Initialize();
}
And here is the interceptor:
public class PresenterInterceptor : IInterceptor
{
    private IDispatcher dispatcher;

    public PresenterInterceptor(IDispatcher dispatcher)
    {
        this.dispatcher = dispatcher;
    }

    public void Intercept(IInvocation invocation)
    {
        object[] attributes = invocation.Method.GetCustomAttributes(typeof (UseDispatcherAttribute), true);
        
        if (attributes.Length == 0)
        {
            invocation.Proceed();
            return;
        }

        dispatcher.RunInUI(invocation.Proceed);
    }
}

Okey so after all that I now discovered that the BackgroundWorker might have been a good choise for this scenario since it has progress event that seems to automatically be executed in the UI thread, I am not sure yet. I will have to try it and do another blog post about it. But I still feel that this solution is nice and easy, and if you use Castle Windsor it is a quick thing to implement.

Ok, maybe a little to much code for a first blogpost, but I named the blog slickcode so why not :)