About this Series
“Adventures in .NET” is a series of articles that aim to expose .NET developers to powerful techniques and concepts to empower them to develop software more productively. The concepts that I present in this series have been gleaned from years of designing and implementing software solutions, and I hope to save you hours of frustration by helping you avoid the pitfalls I experienced through the application of these powerful patterns and practices. While I won’t dive too deep into each subject, I do hope to inspire you to both learn and incorporate these technologies into your work.
All source code for this series can be found on GitHub here:
http://github.com/cstrahan/adventures-in-dotnet
The Problem
As software developers, it is a well known (not to mention begrudging) fact that we spend most of our time maintaining code; anything that we can do to minimize the amount of time spent in “maintenance mode” is a major boon to both our productivity and our esteem, and that entails writing less code in the first place. Unfortunately, there is another well known fact that conspires against our productivity; our codebases tend to be littered with eerily similar code that we just can’t seem to abstract out. An excellent example of this problem is present in any class that implements INotifyPropertyChanged (INPC); every property requires an explicit getter and setter, and the setter must notify the subscribers of the appropriate changes; a perfect example of a DRY violation:
public class PersonViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _firstName;
public string FirstName
{
get
{
return _firstName;
}
set
{
_firstName= value;
RaisePropertyChanged("FirstName");
}
}
private string _lastName;
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName= value;
RaisePropertyChanged("LastName");
}
}
protected void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Polymorphism is great for abstracting out vertical commonality (all objects within a type hierarchy share the same traits; a dog is an animal); however, OOP doesn’t provide us with a solution for abstracting out the horizontal aspects (e.g. INPC, logging all method invocations, auditing changes to Entities, etc). What we need is a means to abstract out the common aspects of our objects’ functions; this is where Aspect Oriented Programming (AOP) steals the lime light.
Solutions
While C# as a language doesn’t provide any syntactic means for applying AOP (unlike some languages, such as as AspectJ), we do have several options at the CLR level: proxies (dynamic/remote) and post-compile static IL-weaving. We’ll take a look at each of these in turn.
Dynamic Proxies
A dynamic proxy class is a class that implements a list of interfaces specified at runtime such that a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface. Thus, a dynamic proxy class can be used to create a type-safe proxy object for a list of interfaces without requiring pre-generation of the proxy class, such as with compile-time tools.
(http://download.oracle.com/javase/1.4.2/docs/api/java/lang/reflect/Proxy.html)
A dynamic proxy class may be thought of as a decorator class that is emitted at runtime; you must make all of your intercepted methods and properties abstract or virtual if you wish for the generated class to derive from your target class (a class proxy), or you may specify an interface for the generated class to impliment (an interface proxy), in which case you may leave your members non-virtual. There are two excellent .NET libraries that help in constructing dynamic proxies: Castle’s DynamicProxy and LinFu. While both are great libraries, let’s take a look at Castle’s DynamicProxy.
DynamicProxy supports both class proxies and interface proxies, which are created through the instance methods of the ProxyGenerator class. The ProxyGenerator constructs proxies that delegate control to a list of one or more IInterceptors that you provide. Let’s take a look at the definition for the IInterceptor interface:
public interface IInterceptor
{
void Intercept(IInvocation invocation);
}
All of the magic happens inside of the Intercept method; it provides you with all of the info regarding the current method invocation in the aptly named invocation argument, and it allows you to handle the invocation as you see fit. You can proceed with the invocation by calling invocation.Proceed, inspect the arguments with invocation.Arguments, view the MethodInfo via invocation.Method, etc. In our case, we will use this as an opportunity to encapsulate our aspects.
For those familiar with dynamic languages, this is akin to having Ruby’s method_missing within a static type system; the difference is that we can only intercept methods that are defined on our proxy class.
That’s enough theory; let’s take a look at a concrete example (heavily inspired by this post from Sebastien Lambla’s blog):
public class PersonViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[Notify]
public virtual string FirstName { get; set; }
[Notify]
public virtual string LastName { get; set; }
}
public class NotifyAttribute : Attribute { }
public class NotifyPropertyChangedInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
// let the original call go through first, so we can notify *after*
invocation.Proceed();
if (invocation.Method.Name.StartsWith("set_"))
{
string propertyName = invocation.Method.Name.Substring(4);
var pi = invocation.TargetType.GetProperty(propertyName);
// check that we have the attribute defined
if (Attribute.GetCustomAttribute(pi, typeof(NotifyAttribute)) == null)
return;
// get the field storing the delegate list that are stored by the event.
FieldInfo info = invocation.TargetType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
.Where(f => f.FieldType == typeof(PropertyChangedEventHandler))
.FirstOrDefault();
if (info != null)
{
// get the value of the field
PropertyChangedEventHandler evHandler = info.GetValue(invocation.InvocationTarget) as PropertyChangedEventHandler;
// invoke the delegate if it's not null (aka empty)
if (evHandler != null)
evHandler.Invoke(invocation.TargetType, new PropertyChangedEventArgs(propertyName));
}
}
}
}
static void Main(string[] args)
{
var proxyGenerator = new ProxyGenerator();
PersonViewModel personViewModel = proxyGenerator.CreateClassProxy<Personviewmodel>(new NotifyPropertyChangedInterceptor());
personViewModel.PropertyChanged += (src, prop) => Console.WriteLine(prop.PropertyName);
personViewModel.FirstName = "Charles";
personViewModel.LastName = "Strahan";
}
As you can see, we’ve made the code simpler while also making our intent much more clear – a win/win result.
If you want a more detailed look at DynamicProxy, look no further than Krzysztof Kozmic’s excellent tutorial. Likewise, there is an excellent tutorial for LinFu on CodeProject by Philip Laureano – LinFu’s author.
Remote Proxies
The .NET remoting infrastructure can be used to intercept method invocations by hooking into the message sink chain, allowing us to apply our aspects. We’ll use a custom IMessageSink implementation to intercept messages to our remote proxy:
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
namespace RemoteProxy
{
public class AutoNotifySink : IMessageSink
{
private readonly MarshalByRefObject _target;
public AutoNotifySink(MarshalByRefObject target, IMessageSink nextSink)
{
_target = target;
NextSink = nextSink;
}
public IMessageSink NextSink { get; private set; }
public IMessage SyncProcessMessage(IMessage msg)
{
var returnedMessage = (IMethodReturnMessage)NextSink.SyncProcessMessage(msg);
TryRaisePropertyChanged((IMethodMessage)msg);
return returnedMessage;
}
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
throw new InvalidOperationException();
}
private void TryRaisePropertyChanged(IMethodMessage methodMessage)
{
if (methodMessage.MethodName.StartsWith("set_"))
{
var propertyName = methodMessage.MethodName.Substring(4);
var type = Type.GetType(methodMessage.TypeName);
var pi = type.GetProperty(propertyName);
// check that we have the attribute defined
if (Attribute.GetCustomAttribute(pi, typeof(NotifyAttribute)) != null)
{
// get the field storing the delegate list that are stored by the event.
FieldInfo info = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
.Where(f => f.FieldType == typeof(PropertyChangedEventHandler))
.FirstOrDefault();
if (info != null)
{
// get the value of the field
var handler = info.GetValue(_target) as PropertyChangedEventHandler;
// invoke the delegate if it's not null (aka empty)
if (handler != null)
handler.Invoke(_target, new PropertyChangedEventArgs(propertyName));
}
}
}
}
}
}
Now that we have a custom a custom message sink, we’ll need some way to specify that this message sink should be used:
using System;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
namespace RemoteProxy
{
public class AutoNotifyContextProperty : IContextProperty, IContributeObjectSink
{
public string Name
{
get
{
return "AutoNotify";
}
}
public bool IsNewContextOK(Context ctx)
{
return true;
}
public void Freeze(Context ctx)
{ }
public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
{
var notifySink = new AutoNotifySink(obj, nextSink);
return notifySink;
}
}
[AttributeUsage(AttributeTargets.Class)]
public class INPCAttribute : ContextAttribute
{
public INPCAttribute()
: base("INPCAttribute")
{
}
public override void GetPropertiesForNewContext(IConstructionCallMessage ctor)
{
IContextProperty notifyProperty = new AutoNotifyContextProperty();
ctor.ContextProperties.Add(notifyProperty);
}
}
}
Now we just apply that attribute like so:
using System;
using System.ComponentModel;
namespace RemoteProxy
{
[INPC]
public class PersonViewModel : ContextBoundObject, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[Notify]
public string FirstName { get; set; }
[Notify]
public string LastName { get; set; }
}
}
As you can see, this was relatively straightforward. One of the nice things about this implementation is that we don’t need to explicitly wrap the target class in proxy – it’s all transparent. However, this does require that we inherit from ContextBound object, and the performance is considerably lower than with the dynamic proxy.
Post-Compile Static IL-Weaving
IL-weaving is another approach to AOP in .NET. Instead of trying to intercept messages via proxies, a second step can be added to the build process that “weaves in” the necessary IL into the emitted assemblies.
Jb Evain’s Mono.Cecil library is excellent for manipulating IL; when combined with a custom build task, it can make for an excellent AOP tool (Justin Angel has an excellent tutorial). The only down side to using Mono.Cecil is that you have to manipulate the individual IL opcodes (Cecil is meant for generic IL manipulation). Alternatively, If you have some money to spare, PostSharp is an excellent product that takes much higher-level approach to IL-weaving, providing an API similar to DynamicProxy’s IInterceptor.
For the sake of brevity, I won’t be including any code samples for this approach.
Conclusion
AOP is a powerful technique that, when used appropriately, can greatly simplify your projects. Common activities such as logging, auditing and caching can all be abstracted away using the aforementioned techniques. I encourage you to consider how these techniques can be applied to your current project(s). If you have any questions, please feel free to email me at charles.c.strahan