Null Checks for Event Handlers, an Aspect Solution

There is no denying events in C# are a great step forward from more traditional approaches where a lot of boilerplate code needed to be written. I choose C# events over Java’s solution to the Observer pattern any day.

… but, there is one pesky little issue I have with them. By design, it’s really easy to introduce bugs using them. How often have you encountered a NullReferenceException because you didn’t check whether an event handler was null prior to calling it? As a more experienced developer you might choose one out of the following two options.

1. Repeated null checks

Always check whether an event isn’t null prior to calling it. Additionally, you need to copy the event handler to a local variable, otherwise another thread might unsubscribe from the event causing the handler to be null again after you did the null check.

EventHandler handler = SomeEvent;
if ( handler != null )
{
    handler( ... );
}

2. Always subscribe one empty delegate

There might be a small cost of constantly having to call one extra function when the event is raised, but it solves the problem of having to do repeated null checks throughout the code while simultaneously solving the multi-threading issue.

public event EventHandler SomeEvent = delegate {};

The Aspect way

I prefer the second approach, and don’t see any reason why it shouldn’t be used by default, other than a smarter compiler which could take care of this in a ‘cleaner’ manner. That’s why over the weekend I’ve spent some time seeing how PostSharp could help solving this cross-cutting concern. I always love showing off the result prior to explaining how I got there. It’s usage is a one liner.

[assembly: InitializeEventHandlers( AttributeTargetTypes = "Laevo.*" )]
namespace Laevo { ... }

Adding this one attribute prevents you from having to worry about events throughout the entire namespace it applies to.

How does it work?

First of all, you will need PostSharp. That’s not necessarily a bad thing, because if you are fortunate enough to be allowed to use it, or you can simply decide for yourself to buy it, you will greatly appreciate it for more than just this one possible use case.

The InitializeEventHandlersAttribute is called an aspect which is applied on events. However, using a feature of PostSharp called ‘multicasting’, you are able to apply the attribute (MulticastAttribute) on higher level elements, allowing you to choose which one of the lower level elements the aspect should apply to. In the code above, the aspect is applied on an entire assembly, but the aspect knows it should only be applied to events, which is further narrowed down using the AttributeTargetTypes parameter to events within the namespace “Laevo”, and all sub-namespaces. In order to remind the developer that a certain part of his code is enhanced by an aspect, a visualization as follows is visible within Visual Studio.

The code is short enough to paste in its entirety now, but I’ll decompose it in a minute.

[AttributeUsage( AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Event )]
[MulticastAttributeUsage( MulticastTargets.Event, AllowMultiple = false )]
[AspectTypeDependency(
    AspectDependencyAction.Commute,
    typeof( InitializeEventHandlersAttribute ) )]
[Serializable]
public class InitializeEventHandlersAttribute : EventLevelAspect
{
	[NonSerialized]
	Action<object> _addEmptyEventHandler;

	[OnMethodEntryAdvice, MethodPointcut( "SelectConstructors" )]
	public void OnConstructorEntry( MethodExecutionArgs args )
	{
		_addEmptyEventHandler( args.Instance );
	}

	IEnumerable<ConstructorInfo> SelectConstructors( EventInfo target )
	{
		return target.DeclaringType.GetConstructors(
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
	}

	public override void RuntimeInitialize( EventInfo eventInfo )
	{
		base.RuntimeInitialize( eventInfo );

		// Construct a suitable empty event handler.
		MethodInfo delegateInfo = DelegateHelper.MethodInfoFromDelegateType(
                    eventInfo.EventHandlerType );
		ParameterExpression[] parameters = delegateInfo.GetParameters().Select( p =>
                    Expression.Parameter( p.ParameterType ) ).ToArray();
		Delegate emptyDelegate = Expression.Lambda(
                    eventInfo.EventHandlerType, Expression.Empty(),
                    "EmptyDelegate", true, parameters ).Compile();

		// Create a delegate which adds the empty handler to an instance.
		_addEmptyEventHandler = instance => eventInfo.AddEventHandler( instance, emptyDelegate );
	}
}

The steps I followed to create this aspect are documented in the PostSharp 2.1 Documentation “Adding Behaviors to Members”.

  1. Create a new class, deriving from the relevant aspect class. Since I am creating an aspect which is applied on events, I used EventLevelAspect.
  2. Choose on which part of the code your aspect will have effect. This is called an ‘advice’. Although my aspect is applied on events, the solution I used is to add an empty event handler to the events by default. This is something which can be done from the constructor. Therefore I had to use an OnMethodEntryAdvice in order to add this code to the beginning of every constructor.
[OnMethodEntryAdvice, MethodPointcut( "SelectConstructors" )]
public void OnConstructorEntry( MethodExecutionArgs args )
{
	_addEmptyEventHandler( args.Instance );
}
  1. Choosing a ‘pointcut’ is required to determine where the code needs to be added. We’ve already established it needs to be added to the start of methods by using OnMethodEntryAdvice, but we haven’t established which methods it needs to be applied to yet. By using a MethodPointcut, this task is delegated to a separate method of which you pass the name. In my case, this method doesn’t do much more than returning all the constructors of the current type.
IEnumerable<ConstructorInfo> SelectConstructors( EventInfo target )
{
	return target.DeclaringType.GetConstructors(
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
}
  1. We are nearly done, although there is one part of the code I skipped over which is quite interesting nonetheless. The OnMethodEntryAdvice calls the delegate _addEmptyEventHandler(), but where did this come from? Overriding RuntimeInitialize gives you the chance to initialize objects which the advice will require for the specific element the aspect applies to. Using reflection to analyze the passed EventInfo object, a suitable empty event handler can be constructed using Expression Trees. This is required since we don’t have the luxury of using an equivalent to ‘delegate {}’. Finally a simple delegate is created which can add the empty delegate to the event of any given instance.
public override void RuntimeInitialize( EventInfo eventInfo )
{
	base.RuntimeInitialize( eventInfo );

	// Construct a suitable empty event handler.
	MethodInfo delegateInfo = DelegateHelper.MethodInfoFromDelegateType( eventInfo.EventHandlerType );
	ParameterExpression[] parameters = delegateInfo.GetParameters().Select( p => Expression.Parameter( p.ParameterType ) ).ToArray();
	Delegate emptyDelegate
		= Expression.Lambda( eventInfo.EventHandlerType, Expression.Empty(), "EmptyDelegate", true, parameters ).Compile();

	// Create a delegate which adds the empty handler to an instance.
	_addEmptyEventHandler = instance => eventInfo.AddEventHandler( instance, emptyDelegate );
}

… and all that just to eliminate ‘= delegate {}’? Yes, I can be quite stubborn sometimes. 🙂

UPDATE:

This code has since been slightly altered in order to also support events with generic parameters within generic types. Thank you Anupheaus, for reporting this issue! Be sure to check out the latest code on github. A discussion of the problem, and how to work around it can be found in my answer on Stack Overflow.

Aspects and Garbage Collection

Earlier today I wrote about an Assert method which can be used in unit tests to check whether or not an object is collected during Garbage Collection (GC). I wrote this method because I was suspicious about a certain PostSharp Aspect I just implemented. The aspect works great, and I’ll surely write about it later; however, since it’s an aspect which is meant to be applied on an entire assembly by using multicasting, I thought twice before calling it a day.

After being skeptical and writing unit tests to ensure my IsGarbageCollected() method was actually working as expected, I came to the unfortunate conclusion that my aspects were keeping my objects in memory!

It only makes sense really; why wouldn’t aspects be able to keep objects alive? It might not be the first thing you think about, but hopefully this post makes you aware of the hidden dangers. As an example I’ll show you a very basic aspect, and how to fix it.

[Serializable]
public class SampleAspect : IInstanceScopedAspect
{
	[NonSerialized]
	object _instance;

	public object CreateInstance( AdviceArgs adviceArgs )
	{
		_instance = adviceArgs.Instance;
		return MemberwiseClone();
	}

	public void RuntimeInitializeInstance()	{ }
}

As any other memory leak, it suffices to leave one reference lying around to an object, preventing the GC from collecting it. There are two mistakes in the previous code, can you find them?

The first one was most obvious to me. _instance is holding a reference to the object, keeping it alive. Luckily .NET offers us an easy solution, WeakReference. A WeakReference references an object while still allowing that object to be reclaimed by garbage collection.

[Serializable]
public class SampleAspect : IInstanceScopedAspect
{
	[NonSerialized]
	WeakReference _instance;

	public object CreateInstance( AdviceArgs adviceArgs )
	{
		_instance = new WeakReference( adviceArgs.Instance );
		return MemberwiseClone();
	}

	public void RuntimeInitializeInstance()	{ }
}

However, Gael was kind enough to quickly point out this wasn’t the real issue. PostSharp uses prototypes to initialize its aspects. An existing prototype object is cloned to create new aspects. The CreateInstance() method is called on the prototype object, and you are expected to return a new aspect. The real error in my code was I was setting _instance on the prototype, while I should be setting it on the cloned object instead. The prototype object is kept in memory by PostSharp, and as a result the last created object was also held in memory. Not a big issue, but the following implementation is a bit cleaner.

[Serializable]
public class SampleAspect : IInstanceScopedAspect
{
	[NonSerialized]
	object _instance;

	public object CreateInstance( AdviceArgs adviceArgs )
	{
		var newAspect = (InitializeEventHandlerAspect)MemberwiseClone();
		newAspect._instance = adviceArgs.Instance;

		return newAspect;
	}

	public void RuntimeInitializeInstance()	{ }
}

No need to use WeakReference any longer, although I imagine it might still be useful in other scenarios.

Aspect powered WPF

In some of my first posts – as it turns out I can almost celebrate one year of blogging! – I wrote about a factory approach to solve the complexities and overhead of creating dependency properties (DPs) for a WPF control; and notify properties and commands for a viewmodel. Both are essential parts when using WPF and following the MVVM pattern. To summarize: the approach was basically to delegate the creation of these complex components to a factory contained within the class which uses annotations on fields (attributes) to clarify what should be created. To create DPs, this looked as follows:

public class HelloWorldControl : UserControl
{
    [Flags]
    public enum Properties
    {
        Hello,
        World
    {

    static readonly DependencyPropertyFactory<Properties> PropertyFactory
        = new DependencyPropertyFactory<Properties>( false );

    [DependencyProperty( Properties.Hello )]
    public string Hello
    {
        get { return (string)PropertyFactory.GetValue( this, Properties.Hello ); }
        set { PropertyFactory.SetValue( this, Properties.Hello, value ); }
    }

    [DependencyProperty( Properties.World )]
    public string World
    {
        get { return (string)PropertyFactory.GetValue( this, Properties.World); }
        set { PropertyFactory.SetValue( this, Properties.World, value ); }
    }
}

Nice and concise, but as mentioned in my conclusion there is still room for improvement:

  • Requirement of an enum.
  • Having to manually add the factory to the class.
  • Every property has almost the exact same implementation.

As it turns out, PostSharp is the perfect candidate to leverage the concept of Aspect Oriented Programming (AOP) to solve the last two problems, resulting in the following solution:

[WpfControl( typeof( Properties ) )]
public class HelloWorldControl : UserControl
{
    [Flags]
    public enum Properties
    {
        Hello,
        World
    {

    [DependencyProperty( Properties.Hello )]
    public string Hello { get; set; }

    [DependencyProperty( Properties.World )]
    public string World { get; set; }
}

Where does the magic happen?

Simply put, PostSharp does a post-compilation step, inserting the required code where needed. Which code needs to be inserted where is determined by applying aspects (exposed as attributes) to the relevant elements. The WpfControlAttribute in the example above applies an aspect to HelloWorldControl. PostSharp makes it relatively easy by allowing you to implement these aspects by using plain C# classes. It’s a mature framework with an extensive feature set as will become evident from the following more in-depth description.

A core used feature in the implementation is the ability to dynamically ‘provide’ aspects to the elements of your choice. The solution actually is composed of 2 aspects, WpfControlAspect and DependencyPropertyAspect, being applied to the user control and the dependency properties respectively.

  1. The WpfControlAttribute is actually an IAspectProvider, creating a WpfControlAspect and applying it to its target (HelloWorldControl in the example). This extra step is only required for generic aspects as a workaround since C# doesn’t support generic attributes. The generic type arguments are passed as an argument to the attribute, and reflection is used to instantiate the actual generic aspect.
  2. The WpfControlAspect introduces the factory into the user control, and in its turn provides a DependencyPropertyAspect to all members which have the DependencyPropertyAttribute applied to them.
  3. The aspects applied to the properties create the correct call to the DependencyPropertyFactory, where the actual logic is implemented.

This solution represents a personal guideline I prefer to follow when writing aspects.

Only resort to using aspects after applying encapsulation to its fullest extent.

It’s a gut feeling I have, and I can’t quite formulate thorough arguments for it yet. When I can, I’ll be sure to write about it! Perhaps the main advantage is you are less dependant on aspects, and let’s face it, minimizing dependencies is almost always a good thing. Basically I prefer to rely on .NET and its excellent debugging and testing tools as much as possible, and only use PostSharp where .NET fails to satisfy my DRY needs.

Why still use enums?

As explained before, they are a necessary replacement to identify the associated element which is created. They aren’t all that bad. As I will demonstrate in a next post, the enums can even be put to use in some interesting use cases. If you can’t wait, all source code and a particularly interesting unit test is already available for you to try out. If you haven’t installed PostSharp 2.1 RC2 or higher yet, you will need it! Actually I already discussed another use case in a previous post: binding from XAML to a command in the viewmodel by using a custom ‘CommandBinding‘ markup extension and passing the enum as a parameter.

It could be worthwhile to investigate an opt-in approach where only those elements which need to be identified from elsewhere need to be assigned an ID. At first sight it looks like the limitations for attribute arguments are a big deal breaker.

You’re breaking the conventions!

The only convention I am still breaking is that I’m not adding the DependencyProperty fields. As discussed before, I see no need why these are required. The sole stated problem is that tools could rely on this convention to access the properties. Opening a simple user control enhanced with aspect goodiness shows that both Blend and the Visual Studio designer work as expected. That’s good enough for me!