zoukankan      html  css  js  c++  java
  • castle.dynamicProxy学习笔记

    目的:

    可以将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

  • 相关阅读:
    jQuery ajax中支持的数据类型
    行内元素与块级元素
    本地连接无法加载远程访问连接管理器服务,错误711
    SQL Server 两种判断表名是否存在且删除的方式
    SQL Server 2008 修改表名
    MySql5.1在Win7下的安装与重装问题的解决
    JavaScript关闭浏览器
    SQL Server 添加一条数据获取自动增长列的几种方法
    获取当前程序运行目录
    字符串的判断与替换
  • 原文地址:https://www.cnblogs.com/foreachlife/p/castleproxy.html
Copyright © 2011-2022 走看看