(转)MEF+Unity
http://www.dotnetspark.com/kb/4659-mef--unity-interception.aspx
MEF + Unity Interception
Posted By:Mahadesh Mahalingappa Posted Date: August 06, 2011 Points: 200 Category: C# URL: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
|
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.
Prerequisites
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 Application 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, the developer can structure the 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 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
Let's 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 this link.
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
Let's discuss about the Interceptor which is the 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 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 theGetRequiredInterfaces() method. So this method acts as a Dependency Resolver.
public IEnumerable 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 istrue, 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 by concentrating on creating an application which would make extensibility work with AOP.