前言
MEF很好的解决了扩展性问题,但本身不具有拦截器的功能,但是我们在应用程序中为了权限控制,日志记录等,却又需要拦截(AOP)器功能,本文主要介绍使用MEF+Unity实现可扩展的拦截器,使得我们的应用程序既具有可扩展性,又能实现拦截。
先决条件
1. 你需要了解MEF和Unity Framework的基本知识;
2. 下载MEF Contrib (点击这里下载),MEF Contrib提供了支持Unity的拦截器扩展:CompositionIntegration;
3. 下载Unity Application Block DLLs,点击这里下载;
有了这些dll,我们就可以实现我们的MEF+Unity Interception。
工作原理
上图中的Unity + MEF Integration Layer ,是一个中间层,由MEFContrib中的MefContrib.Integration.Unity.dll实现。它使得MEF组件可以自动注入到Unity组件中,反之,Unity组件也可注入到MEF组件中。这便使得我们的程序可以同时使用MEF和Unity并发挥他们各自的优势。
实现
1.新建项目MEFWithUnityInterceptionDemo,新建目录RefenceLib,将上面下载的dll拷贝到该目录中,并添加Unity和MEFContrib相关dll的引用。
2.添加ILogger接口及其实现类ConsoleLogger,并将ConsoleLogger标记为导出:
1 /// <summary>
2 /// 日志接口
3 /// </summary>
4 public interface ILogger
5 {
6 void Write(string message);
7 }
8
9 /// <summary>
10 /// Logger,导出类型为ILogger
11 /// </summary>
12 [Export(typeof(ILogger))]
13 public class ConsoleLogger : ILogger
14 {
15 public void Write(string message)
16 {
17 Console.WriteLine(message);
18 }
19 }
3.定义拦截器Interceptor,并定义导入类型为ILogger的导入。自定义拦截器using命名空间:Microsoft.Practices.Unity.InterceptionExtension,并实现IInterceptionBehavior。这是实现对Logger的方法拦截很重要的一步。
1 /// <summary>
2 /// 自定义拦截器
3 /// </summary>
4 public class Interceptor : IInterceptionBehavior
5 {
6 /// <summary>
7 /// 导入日志对象
8 /// </summary>
9 [Import]
10 public ILogger Logger { get; set; }
11
12 public Interceptor()
13 {
14 }
15
16 public IEnumerable<Type> GetRequiredInterfaces()
17 {
18 return Type.EmptyTypes;
19 }
20
21 public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
22 {
23 IMethodReturn msg = null;
24 //方法调用前
25 Logger.Write("Hello World + Pre Calling");
26
27 // 方法调用
28 msg = getNext()(input, getNext);
29
30 //调用后
31 Logger.Write("Hello World + Post Calling");
32
33 return msg;
34 }
35
36 /// <summary>
37 /// 指定是否拦截
38 /// </summary>
39 public bool WillExecute
40 {
41 get
42 {
43 return true;
44 }
45 }
46 }
对自定义拦截器的几点说明:
a.WillExecute属性指定是否需要拦截,这里默认返回true,
b.在Invork方法中实现拦截后需要执行的相关处理;
c.代码"msg = getNext()(input, getNext);"可以调用到被拦截的真实方法,在它的前后我们处理拦截逻辑。
4.添加接口IApplication及其实现类Application。Application负责创建MEF容器并组合。对ILogger方法调用是在这里触发的。而且这里的方法调用,我们希望可以被前面定义的拦截器捕获到,已证明我们的拦截器有作用。
1 /// <summary>
2 /// IApplication接口
3 /// </summary>
4 public interface IApplication
5 {
6 void Run();
7 }
8 /// <summary>
9 /// Application
10 /// </summary>
11 public class Application : IApplication
12 {
13 [Import]
14 public ILogger Logger { get; set; }
15
16 public Application()
17 {}
18
19 /// <summary>
20 /// 请注意这里的虚方法
21 /// </summary>
22 public virtual void Run()
23 {
24 //创建目录
25 var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
26 //创建组合容器
27 var container = new CompositionContainer(catalog);
28 //组合部件
29 container.ComposeParts(this);
30 //调用方法
31 Logger.Write("Helloworld");
32 }
33 }
5.在program中创建Unity容器,并添加MEF和Unity的中间层扩展CompositionIntegration,并将拦截器的Catalog加入到CompositionIntegration的组合目录中,实现拦截器中部件成功组合。具体实现如下,代码中有注释:
1 // 创建unity容器
2 var unityContainer = new UnityContainer();
3 var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
4
5 //注册MefContrib提供拦截扩展
6 unityContainer.AddNewExtension<CompositionIntegration>();
7 //注册自定义的拦截器扩展
8 unityContainer.AddNewExtension<Interception>();
9
10 //在unity容器中注册类型,并指定拦截虚方法,指定拦截器为Interceptor
11 unityContainer.RegisterType<IApplication, Application>(new Interceptor<VirtualMethodInterceptor>(), new InterceptionBehavior<Interceptor>());
12
13 //配置MefContrib提供的组合拦截器
14 CompositionIntegration integration = unityContainer.Configure<CompositionIntegration>();
15 //指定需要组合的目录
16 integration.Catalogs.Add(assemblyCatalog);
17
18 //从容器中获取Application的实例
19 IApplication app = unityContainer.Resolve<Application>();
20
21 app.Run();
22
23 Console.ReadLine();
至此我们实现了利用MEF和Unity实现一个可扩展的拦截器功能。运行效果如下:
最终代码结构如下:
示例源码下载地址:MEFWithUnityInterceptionDemo.7z
本文主要参考:http://www.dotnetspark.com/kb/4659-mef--unity-interception.aspx