文章出處

目的:

可以將castle.dynamicProxy當成代碼生成器,快速的生成自己想的代碼.這個庫經歷了這么多年的測試,應該可以用了:D

概念:

IInterceptor:攔截器

當方法(屬性的本質是兩個方法的組合)被調用時,則執行這個攔截器的代碼.

但是,默認情況下,一個方法的調用被生成了一個攔截器.如果用于DC代碼生成,這似乎有點浪費資源.

public class SimpleLogInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine(">>" + invocation.Method.Name);
        invocation.Proceed();
    }
}

測試:

ProxyGenerator generator = new ProxyGenerator();
SimpleSamepleEntity entity
= generator.CreateClassProxy<SimpleSamepleEntity>( new SimpleLogInterceptor(), new CallingLogInterceptor()); //這里可以指定多個攔截器 entity.Name = "Richie"; entity.Age = 50; Console.WriteLine("The entity is: " + entity); Console.WriteLine("Type of the entity: " + entity.GetType().FullName); Console.ReadKey();

 

 IInterceptorSelector 與 IProxyGenerationHook

實際中并不一定所有方法都需要運用全部的攔截器,對方法調用有選擇性的選擇攔截器有2種方式,例如:

public class InterceptorSelector : IInterceptorSelector
{
    public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors)
    {
        if (method.Name.StartsWith("set_")) return interceptors;    //這里可以決定什么的方法返回什么樣的攔截器
        else return interceptors.Where(i => i is CallingLogInterceptor).ToArray<IInterceptor>();
    }
}
public class InterceptorFilter : IProxyGenerationHook { public bool ShouldInterceptMethod(Type type, MethodInfo memberInfo) { return memberInfo.IsSpecialName && (memberInfo.Name.StartsWith("set_") || memberInfo.Name.StartsWith("get_")); //什么樣的方法可以被攔截? } public void NonVirtualMemberNotification(Type type, MemberInfo memberInfo) {
      //類型為非虛方法時,這里可以得到提示,將被調用 }
public void MethodsInspected() { } }

測試代碼:

ProxyGenerator generator = new ProxyGenerator();
var options = new ProxyGenerationOptions(new InterceptorFilter()) { Selector = new InterceptorSelector() };
SimpleSamepleEntity entity = generator.CreateClassProxy<SimpleSamepleEntity>(
    options,
    new SimpleLogInterceptor(), new CallingLogInterceptor());
entity.Name = "Richie";
entity.Age = 50;
Console.WriteLine("The entity is: " + entity);
Console.WriteLine("Type of the entity: " + entity.GetType().FullName);
Console.ReadKey();

IProxyGenerationHook接口決定整個方法是否運用攔截器,他是在動態構造代理類型的時候使用的;而IInterceptorSelector接口決定某個方法該運用哪些攔截器,他在每次調用被攔截的方法時執行
上面的示例只對setter和getter方法進行攔截,并且對getter方法只使用CallingLogInterceptor這個攔截器

 

導出、生成代理類型
Castle Dynamic Proxy允許我們將運行時生成的代理類型生成dll文件存到磁盤上,下次啟動時通過加載這個dll文件可以避免動態生成代理類型

var scope = new ModuleScope(
    true,
    ModuleScope.DEFAULT_ASSEMBLY_NAME,
    ModuleScope.DEFAULT_FILE_NAME,
    "DynamicProxyTest.Proxies",
    "DynamicProxyTest.Proxies.dll");
var builder = new DefaultProxyBuilder(scope);
var generator = new ProxyGenerator(builder);
var options = new ProxyGenerationOptions(new InterceptorFilter())
{
    Selector = new InterceptorSelector()
};
SimpleSamepleEntity entity = generator.CreateClassProxy<SimpleSamepleEntity>(
    options,
    new SimpleLogInterceptor(), new CallingLogInterceptor());
IStorageNode node = generator.CreateInterfaceProxyWithTargetInterface<IStorageNode>(
    new StorageNode("master")
    , new DualNodeInterceptor(new StorageNode("slave"))
    , new CallingLogInterceptor());
options = new ProxyGenerationOptions();
options.AddMixinInstance(new ClassA());
ClassB objB = generator.CreateClassProxy<ClassB>(options, new CallingLogInterceptor());
scope.SaveAssembly(false);

注意:上面用到的攔截器和其他測試類都必須加上[Serializable]屬性
可以用reflector查看生成的dll,大致了解代理對象是如何工作的
啟動時,可以使用
scope.LoadAssemblyIntoCache(assembly);
將生成的代理類型加載到內存中,其中assembly需要我們手動加載

參考原文:

http://www.cnblogs.com/RicCC/archive/2010/03/15/castle-dynamic-proxy.html


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()