MEF + Unity Interception
Scope of this Article :
In this article I try to use MEF with Unity Framework. I am trying to build a
simple app which would be extensible and at the same time would use Aspect
Oriented Concept.
http://en.wikipedia.org/wiki/Aspect-oriented_programming.
Prerequisite :
Basic knowledge of MEF and Unity framework.
Step 1 :
A. Download the MEF Contrib from the site http://mefcontrib.codeplex.com/
Question to be asked is why should you download MEF Contrib when you already
have MEF DLLs with you. Well the MEF DLLs do not provide us the Layer which
integrates with the Unity Framework. Hence MEF Components cannot be accessed by
Unity Framework and vice versa.
B. Download the Unity Applicaion Block Dlls from the site
http://www.microsoft.com/download/en/details.aspx?id=9093
Once we have the DLLs downloaded we can start with coding. Before coding let's
get some understanding of what we are trying here.
We are going to use MEFContrib to provide an Extensibility to our application
and Unity Framework so that we can bring the concept of Aspect Oriented
Programming.
Unity + MEF Integration Layer is a middle component (implemented as
MefContrib.Integration.Unity.dll) that combines the strength of both frameworks
and allows great extensibility. Using integration layer, developer can structure
application's backbone using Unity while leaving the extensibility part to MEF
as you can see from the figure below.
What the layer actually does is that it makes MEF components (i.e. components
known to MEF) available to the Unity by automatically injecting them into Unity
components (i.e. components registered in the Unity container), and vice versa.
This "synchronization " can be either one-way or two way. In the first case,
Unity will know about MEF components (but MEF will know nothing about Unity),
thus Unity will be able to inject MEF components into Unity ones. The opposite
synchronization, in which MEF will know about Unity's components, is also
possible but is unlikely to be used. In the second scenario, both MEF and Unity
know about each other, enabling both frameworks to use each other components.
Step 2 :
I have added all the DLLs and dependency DLLs (not necessary to add as
references )required for this application as shown below:
Step 3 :
public interface
ILogger
{
void Write(string
message);
}
Creating the Console Logger:
using
System.ComponentModel.Composition;
[Export(typeof(ILogger))]
public class
ConsoleLogger :
ILogger
{
public void
Write(string message)
{
Console.WriteLine(message);
}
}
Creating the Interceptor:
The Interceptor code would look like below:
using
Microsoft.Practices.Unity.InterceptionExtension;
using
System.ComponentModel.Composition;
public
class Interceptor
: IInterceptionBehavior
{
[Import]
public
ILogger Logger { get;
set; }
public Interceptor()
{
}
public
IEnumerable<Type>
GetRequiredInterfaces()
{
return
Type.EmptyTypes;
//return null;
}
public
IMethodReturn Invoke(IMethodInvocation
input, GetNextInterceptionBehaviorDelegate
getNext)
{
IMethodReturn msg =
null;
//Pre method calling
Logger.Write("Hello
World + Pre Method Calling")
// Method is invoked
msg = getNext()(input, getNext);
//Post method calling
Logger.Write("Hello
World + Post Method Calling");
return msg;
}
public bool
WillExecute
{
get
{
return
true;
}
}
}
Create an Interface for the
Application Class.
public interface
IApplication
{
void Run();
}
Application class looks as below:
using
System.ComponentModel.Composition;
using
System.ComponentModel.Composition.Hosting;
using
System.Reflection;
public class
Application :
IApplication
{
[Import]
public ILogger
Logger { get; set;
}
public virtual
void Run()
{
var catalog =
new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container =
new
CompositionContainer(catalog);
container.ComposeParts(this);
Logger.Write("Helloworld");
Console.ReadLine();
}
}
Final structure:
Lets give it a run:
Using Interception with Unity:
Interception is a design pattern that is designed for cross-cutting concerns,
issues that cut across the entire software. You can intercept a method call
after the method call has been made. In short, It's a method of achieving Aspect
Oriented Programming.
Unity provides support for interception through the Interception container
extension.
To get an insight into what Interception is check out the link http://msdn.microsoft.com/en-us/library/ff647107.aspx
VirtualMethodInterceptor:
A type interceptor. It uses dynamic code generation to create a derived class
that gets instantiated instead of the original, intercepted class and to hook up
the call handlers.
Use:
Lets Discuss about the Interceptor which is key component.
Interceptor is a class which implements the interface
Microsoft.Practices.Unity.InterceptionExtension.IInterceptionBehavior.
IInterceptionBehavior:
namespace
Microsoft.Practices.Unity.InterceptionExtension
{
public interface
IInterceptionBehavior
{
bool WillExecute {
get; }
IEnumerable<Type>
GetRequiredInterfaces();
IMethodReturn Invoke(IMethodInvocation
input, GetNextInterceptionBehaviorDelegate
getNext);
}
}
Resolving the Dependencies for
the Unity Container:
When a call is made to the Resolve Method on the Unity container dependencies
are fetched using the GetRequiredInterfaces() Method. So this method acts as a
Dependency Resolver.
public
IEnumerable<Type>
GetRequiredInterfaces()
{
return
Type.EmptyTypes;
}
Turning the Interceptor On and Off:
This property lets the Interceptor know whether it has to intercept the method
call or not. If WillExecute is true, the interceptor would be activated, a false
would deactivate the interceptor
public
bool WillExecute
{
get
{
return
true;
}
}
public
IMethodReturn Invoke(IMethodInvocation
input, GetNextInterceptionBehaviorDelegate
getNext)
{
IMethodReturn msg =
null;
//Pre method calling
Logger.Write("Hello
World + Pre Method Calling");
msg = getNext()(input, getNext);
<= Method invoked
//Post method calling
Logger.Write("Hello
World + Post Method Calling");
Console.ReadLine();
return msg;
}
We can debug and check out how the
method behaves. The msg returns with an Exception of null which confirms that
the Interception call is successfully completed.
Conclusion:
In this example I tried to keep things simple concentrating on creating an
application which would make extensibility work with AOP.