使用MEF與Castle實現AOP

MEF是微軟的一個ioc框架,使用非常方便,我們只需要在需要導出的類上標記[Export],在需要使用的地方[import]就可以使用了。現在我們擴展MEF,在其裝配生成實例時,使用Castle DynamicProxy對其生成透明代理。
我們先實現一個攔截器,并且繼承Attribute基類,這個我們可以將這個攔截器作為類的特性來使用。
<pre>
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");
}
}
}
</pre>
這個攔截器中,我們對攔截的方法執行前和執行后都增加了操作。

然后我們新增一個類,這個類使我們需要導出的類。
<pre>
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");
}
}
}
</pre>
在這個類上,我們增加特性 [Export(typeof(ClassA))],這是MEF的基本用法。[LogInterceptor]是我們定義的攔截器,我們可以攔截GetA方法。需要攔截的方法必須是虛方法。

下面我們來擴展下MEF。
ExportProvider 類:檢索與指定的 ImportDefinition 對象相匹配的導出。這個類的作用很明確,就是用來尋找與 ImportDefinition 對象匹配的ExportDefinition。
我們新增一個基礎自ExportProvider 的類。
<pre>
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();
    }
}

}
</pre>

在裝配時,會觸發GetExportsCore方法,去尋找相對應的導出。我們在GetValue方法中,使用Castle生成動態代理。
<pre>
IInterceptor[] attribs = t.GetCustomAttributes(typeof(IInterceptor), true).Cast<IInterceptor>().ToArray();
</pre>
上面這行代碼主要是從需要導出的類的自定義特性中,尋找攔截器。我們這里定義的是[LogInterceptor]。
然后我們再生成透明的動態代理
<pre>
ProxyGenerator generator = new ProxyGenerator();
object proxy = generator.CreateClassProxy(value.GetType(), attribs);
</pre>
下面我們新增一個窗體類,窗體上有一個按鈕,點擊按鈕,觸發ClassA實例的GetA方法。看是否可以進行攔截。
<pre>

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();
    }
}

}
</pre>
在代理里,我們定義了一個字段,用來Import ClassA類。
<pre>
[Import(typeof(ClassA))]
private ClassA c1;
</pre>
在我們裝配代碼中,使用我們擴展的AopExportProvider


image.png

我們測試下,點擊按鈕,看看輸出的情況。


image.png

好的,我們成功的攔截了ClassA的GetA方法,并在方法執行前和執行后都增加了操作。
這種AOP的實現,我們只需要在需要導出的類上增加一個特性就行了。如果有其他需求,我們可以再增加攔截器,并在相應的類上增加特性就行了,很方便。美中不足的是,需要按照MEF的方式去生成實例,不能像postsharp那樣。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,868評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,067評論 25 708
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,941評論 6 342
  • 歡迎大家來到今天的《超級個體》實驗群,大家匯聚到群的目標是成為一個超級個體! 工欲善其事必先利其器,想必大家每天除...
    得到超級個體閱讀 739評論 0 2
  • “灼灼荷花瑞,亭亭出水中。一莖孤引綠,雙影共分紅。”碧波蕩漾,微風拂過,荷葉晃動,花瓣輕舞,那一池蓮花,就那樣悄然...
    天若有情716閱讀 305評論 0 0