• 使用MEF与Castle实现AOP


    MEF是微软的一个ioc框架,使用非常方便,我们只需要在需要导出的类上标记[Export],在需要使用的地方[import]就可以使用了。现在我们扩展MEF,在其装配生成实例时,使用Castle DynamicProxy对其生成透明代理。
    我们先实现一个拦截器,并且继承Attribute基类,这个我们可以将这个拦截器作为类的特性来使用。

    using Castle.DynamicProxy;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace MefAopTest
    {
    public class LogInterceptor : Attribute,IInterceptor
    {
    public void Intercept(IInvocation invocation)
    {
    Console.WriteLine("begin");
    invocation.Proceed();
    Console.WriteLine("end");
    }
    }
    }
    View Code

    这个拦截器中,我们对拦截的方法执行前和执行后都增加了操作。

    然后我们新增一个类,这个类使我们需要导出的类。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.Linq;
    using System.Text;
    namespace MefAopTest
    {
    [Export(typeof(ClassA))]
    [LogInterceptor]
    public class ClassA
    {
    public virtual void GetA()
    {
    Console.WriteLine("GetA");
    }
    }
    }
    View Code

    在这个类上,我们增加特性 [Export(typeof(ClassA))],这是MEF的基本用法。[LogInterceptor]是我们定义的拦截器,我们可以拦截GetA方法。需要拦截的方法必须是虚方法。

    下面我们来扩展下MEF。
    ExportProvider 类:检索与指定的 ImportDefinition 对象相匹配的导出。这个类的作用很明确,就是用来寻找与 ImportDefinition 对象匹配的ExportDefinition。
    我们新增一个基础自ExportProvider 的类。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel.Composition.Hosting;
    using System.ComponentModel.Composition.Primitives;
    using Castle.DynamicProxy;
    namespace MefAopTest
    {
    public class AOPExportProvider : ExportProvider, IDisposable
    {
        private CatalogExportProvider _exportProvider;
    
        public AOPExportProvider(Func<ComposablePartCatalog> catalogResolver)
        {
            _exportProvider = new CatalogExportProvider(catalogResolver());
        }
    
        public ExportProvider SourceProvider
        {
            get
            {
                return _exportProvider.SourceProvider;
            }
            set
            {
                _exportProvider.SourceProvider = value;
            }
        }
    
    
        protected override IEnumerable<Export> GetExportsCore(
            ImportDefinition definition, AtomicComposition atomicComposition)
        {
            IEnumerable<Export> exports = _exportProvider.GetExports(definition, atomicComposition);
            return exports.Select(export => new Export(export.Definition, () => GetValue(export)));
        }
    
        private object GetValue(Export innerExport)
        {
            object value = innerExport.Value;
    
            Type t = value.GetType();
            IInterceptor[] attribs = t.GetCustomAttributes(typeof(IInterceptor), true).Cast<IInterceptor>().ToArray();
    
            ProxyGenerator generator = new ProxyGenerator();
            object proxy = generator.CreateClassProxy(value.GetType(), attribs);
            return proxy;
        }
    
    
        public void Dispose()
        {
            _exportProvider.Dispose();
        }
    }
    }

    在装配时,会触发GetExportsCore方法,去寻找相对应的导出。我们在GetValue方法中,使用Castle生成动态代理。

    IInterceptor[] attribs = t.GetCustomAttributes(typeof(IInterceptor), true).Cast<IInterceptor>().ToArray();


    上面这行代码主要是从需要导出的类的自定义特性中,寻找拦截器。我们这里定义的是[LogInterceptor]。
    然后我们再生成透明的动态代理

    ProxyGenerator generator = new ProxyGenerator();
    object proxy = generator.CreateClassProxy(value.GetType(), attribs);


    下面我们新增一个窗体类,窗体上有一个按钮,点击按钮,触发ClassA实例的GetA方法。看是否可以进行拦截。

    namespace MefAopTest
    {
    public : Form
    {
    public Form1()
    {
    InitializeComponent();
    ComposeParts();
    }
        [Import(typeof(ClassA))]
        private ClassA c1;
    
        public  void ComposeParts()
        {
            Func<ComposablePartCatalog> catalogResolver = () =>
            {
    
                var catalog = new AggregateCatalog();
                AssemblyCatalog assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
    
                catalog.Catalogs.Add(assemblyCatalog);
                return catalog;
            };
    
            AOPExportProvider provider = new AOPExportProvider(catalogResolver);
            CompositionContainer container = new CompositionContainer(provider);
            provider.SourceProvider = container;
            container.ComposeParts(this);
        }
    
        private void Test_Click(object sender, EventArgs e)
        {
            c1.GetA();
        }
    }
    }

    在代理里,我们定义了一个字段,用来Import ClassA类。

    [Import(typeof(ClassA))]
    private ClassA c1;


    在我们装配代码中,使用我们扩展的AopExportProvider

     
    image.png

    我们测试下,点击按钮,看看输出的情况。

     
    image.png


    好的,我们成功的拦截了ClassA的GetA方法,并在方法执行前和执行后都增加了操作。
    这种AOP的实现,我们只需要在需要导出的类上增加一个特性就行了。如果有其他需求,我们可以再增加拦截器,并在相应的类上增加特性就行了,很方便。美中不足的是,需要按照MEF的方式去生成实例,不能像postsharp那样。

  • 相关阅读:
    Python反射函数
    类之特性
    ThinkPHP框架基础知识一
    smarty变量调节器与函数
    smarty模板及其应用
    php……流程
    php......权限管理
    php......文件上传
    php......注册审核
    php......留言板
  • 原文地址:https://www.cnblogs.com/czly/p/9109199.html
Copyright © 2020-2023  润新知