Hello,
I’ve found a Microsoft article about Unity and Aspect Oriented programming, and it was really interesting. So, 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, lets get the basis of each of these three main members of my sample:
- Microsoft Unity 2 is a Dependency Injection Framework which also supports which helps us to create loosely couple applications. See details at http://msdn.microsoft.com/en-us/library/dd203101.aspx
- Aspect Oriented Programming ( AOP ) is a development style where the main concerns are separated from the secondary concerts of the application. E.g. you can be able to separate your the logic used to log information from the main business logic of the application. See more info at http://en.wikipedia.org/wiki/Aspect-oriented_programming
- Interceptor design pattern is a software design pattern which allows to insert and configure logic when executing code in given methods. See more info at http://en.wikipedia.org/wiki/Interceptor_pattern
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. So, we define a contract (interface) called IProxy to define the expected behavior of our proxy and let unity know which is the contract. Then we have in a separate project an concrete implementation Proxy which implements the interface. 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 alternative: a configuration file or by writing some code.This will he explain in 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 we only print message about when these calls are performed.
AspectOriented.Terminal’s project
This is the main project which generates the executable file. Here are two important things to point out. Unity has being configured by using the configuration file, however you can use code instead. 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 proxy instance. And this same functionality can be plugged to any other component (instance) by using the same mechanism.
Resources about this topic
- Aspect-Oriented Programming, Interception and Unity 2.0 http://msdn.microsoft.com/en-us/magazine/gg490353.aspx
- Specifying Types in the Configuration File http://msdn.microsoft.com/en-us/library/ff660933%28v=PandP.20%29.aspx
- Extending the Unity Configuration Schema http://msdn.microsoft.com/en-us/library/ff660880%28v=PandP.20%29.aspx
- Configuration Files for Interception http://msdn.microsoft.com/en-us/library/ff660932%28v=PandP.20%29.aspx
- Unity Interception Extension http://www.peternilsson.me/#post14
- Microsoft Unity – code to xml http://stackoverflow.com/questions/640806/microsoft-unity-code-to-xml
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


