RSS

Aspect Oriented Programming and Interceptor design pattern with Unity 2

25 Dec

Hello,

I’ve found a Microsoft article about Unity and Aspect Oriented programming. The article was really interesting. Then, to be the theory in action I’ve decide to exemplify how Unity 2 uses the Interceptor design pattern to support Aspect Oriented Programming (aka AOP).  First of all, let talk about the three key elements involved into this example:

Once again, I’ve decide to use MonoDevelop to create the sample and the source code is available to be downloaded from github at https://github.com/hmadrigal/CodeSamples/tree/master/AspectOriented.Terminal

Sample structure

This example supposes that you have a proxy and want it to add logging information. Thus, we’ve defined a contract (interface) called IProxy to define the expected behavior of our proxy. Then, we have in a separate project an concrete implementation Proxy which implements the interface IProxy. At last but not a least, we have a project which defines a Unity interceptor. All these components are united by the configuration file which lets unity know how these components should interact.

AspectOriented.Infrastructure’s project

This project contains all the common resources and the contracts (interfaces) to be used in the sample. Here is defined the IProxy interface:

using System;
namespace AspectOriented.Infrastructure.Services
{
  public interface IProxy
  {
    bool IsEnabled ();
    void Open ();
    void Close ();
  }
}

AspectOriented.UnityInterceptors’s project

The second project we’re going to talk is where the interceptor is defined. As we’ve already mentioned the interceptor will allow unity to perform tasks before and/or after the intercepted method is invoked. To define  which method is going to be intercepted, we can use two alternatives: 1)a configuration file or 2) by writing some code. I’ll talk about the Unity configuration file once I explain the AspectOriented.Terminal’s project.

using System;
using System.Collections.Generic;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace AspectOriented.UnityInterceptors
{
	public class DiagnosticInterceptor : IInterceptionBehavior
	{
		public DiagnosticInterceptor ()
		{
		}

		#region IInterceptionBehavior implementation
		public IMethodReturn Invoke (IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
		{
			System.Console.WriteLine (String.Format ("[{0}:{1}]", this.GetType ().Name, "Invoke"));

			// BEFORE the target method execution
			System.Console.WriteLine (String.Format ("{0}", input.MethodBase.ToString ()));

			// Yield to the next module in the pipeline
			var methodReturn = getNext ().Invoke (input, getNext);

			// AFTER the target method execution
			if (methodReturn.Exception == null) {
				System.Console.WriteLine (String.Format ("Successfully finished {0}", input.MethodBase.ToString ()));
			} else {
				System.Console.WriteLine (String.Format ("Finished {0} with exception {1}: {2}", input.MethodBase.ToString (), methodReturn.Exception.GetType ().Name, methodReturn.Exception.Message));
			}

			return methodReturn;
		}

		public IEnumerable<Type> GetRequiredInterfaces ()
		{
			System.Console.WriteLine (String.Format ("[{0}:{1}]", this.GetType ().Name, "GetRequiredInterfaces"));
			return Type.EmptyTypes;
		}

		public bool WillExecute {
			get {
				System.Console.WriteLine (String.Format ("[{0}:{1}]", this.GetType ().Name, "WillExecute"));
				return true;
			}
		}
		#endregion
	}
}

As you might noticed the interceptor implements IInterceptionBehavior which will let Unity know that this class can act like an interceptor. To simplify things, the interceptor will print message only when the intercepted method is invoked. The printed information is about the method being invoked. However, interceptors can perform more complex such as starting threads, performing web requests and so on.

AspectOriented.Terminal’s project

This is the main project which generates the executable file. Here are two important things to point out. First we’ve configured our container here. In this case  Unity has being configured by using the configuration file, however you can use code instead. The second, the main application performs calls on the instance that unity resolves, the interception process happens behind scenes and we only will see the result when we call the methods of the proxy.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
	<configSections>
		<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
	</configSections>
	<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
		<!-- Interception is not part of the default Unity configuration schema. -->
		<!-- Before you can configure interception you must add the correct sectionExtension element to your configuration -->
		<!-- section in the configuration file.-->
		<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
		<!-- Defines some aliast to easily manipulate the mappings -->
		<alias alias="IProxy" type="AspectOriented.Infrastructure.Services.IProxy, AspectOriented.Infrastructure" />
		<alias alias="Proxy" type="AspectOriented.Terminal.Services.Proxy, AspectOriented.Terminal" />
		<alias alias="DiagnosticInterceptor" type="AspectOriented.UnityInterceptors.DiagnosticInterceptor, AspectOriented.UnityInterceptors" />
		<!-- Default Container when creating the tree-chain of resolution-->
		<container>
			<!-- Loading the section extension only enables the interception configuration to be given in the configuration file. -->
			<!-- Interception itself will not work unless you also load the interception container extension in your Unity container instance.-->
			<extension type="Interception" />
			<register type="IProxy" mapTo="Proxy">
				<lifetime type="ContainerControlledLifetimeManager" />
				<interceptor type="InterfaceInterceptor" />
				<interceptionBehavior type="DiagnosticInterceptor" />
			</register>
		</container>
	</unity>
</configuration>

The configuration file defines two section which are mandatory to define interceptors, these are sectionExtension and extension. Then into the registration of a given type (or in our sample the IProxy Type) we can define the interceptors for this particular type resolution.

using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;
using AspectOriented.Infrastructure.Services;

namespace AspectOriented.Terminal
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			// Loads the container
			IUnityContainer container = new UnityContainer ();
			container = Microsoft.Practices.Unity.Configuration.UnityContainerExtensions.LoadConfiguration (container);

			// Resolve the proxy-sample
			var proxy = Microsoft.Practices.Unity.UnityContainerExtensions.Resolve<IProxy> (container);
			if (proxy.IsEnabled ()) {
				proxy.Open ();
			}
			proxy.Close ();

			// End of the test
			Console.ReadKey ();
		}
	}
}

At last but not least we’ve our main code. It’s quite straightforward, it creates a Unity container, loads the container configuration from the configuration file, and then uses the container to resolve the given interface (contract). As I mentioned the magic happens behind-scenes, when you call the Proxy methods there is functionality which is going to be injected before and after each call of this instance. Take a look of the final screen-shot to see the all the terminal messages which were triggered during the method calls of the Proxy.

As you can notice the interception calls are injected before and after each call of the intercepted methods of our proxy instance. Furthermore, we can inject the same logic to different contracts (interfaces) by only updating the configuration file. If there is not a contract, it is still possible to perform interception, Unity 2 supports three mechanisms for interception, just keep in mind that each mechanism has its pros and cons.  Remember that same functionality can be plugged to any other component (instance) by using the same mechanism.

Resources about this topic

Once again, I’ve decide to use MonoDevelop to create the sample and the source code is available to be downloaded from github at https://github.com/hmadrigal/CodeSamples/tree/master/AspectOriented.Terminal

About these ads
 
1 Comment

Posted by on 2010/12/25 in .net, c#, developer, mono, programming

 

Tags: , , , , ,

One response to “Aspect Oriented Programming and Interceptor design pattern with Unity 2

  1. Eric

    2012/08/15 at 09:17

    Thank you very much. I found this very useful.

     

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 669 other followers

%d bloggers like this: