现在的位置: 首页 > 综合 > 正文

LinFu Dynamic Proxy – LinFu 2.3, LinFu.DynamicProxy 1.031

2011年10月23日 ⁄ 综合 ⁄ 共 4310字 ⁄ 字号 评论关闭
项目地址:Google CodeGitHub
实现的特性有:
1. AOP
2. Dynamic Proxy
3. Minxins
4. Duck Typing
5. Design by Contract

基本示例

public class SimpleSamepleEntity
{
    public SimpleSamepleEntity()
    {
        Console.WriteLine("create SimpleSamepleEntity");
    }
    public virtual string Name { get; set; }
    public virtual int Age { get; set; }
    public override string ToString()
    {
        return string.Format("{{ Name: \"{0}\", Age: {1} }}", this.Name, this.Age);
    }
}
public class SimpleSampleInterceptor : IInterceptor
{
    private SimpleSamepleEntity _target;
    public SimpleSampleInterceptor(SimpleSamepleEntity target)
    {
        this._target = target;
    }
    public object Intercept(InvocationInfo info)
    {
        Console.WriteLine(">>Intercepting " + info.TargetMethod.Name);
        return info.TargetMethod.Invoke(this._target, info.Arguments);
    }
}
public class SimpleSampleWrapper : IInvokeWrapper
{
    private SimpleSamepleEntity _target;
    public SimpleSampleWrapper(SimpleSamepleEntity target)
    {
        this._target = target;
    }
    public void BeforeInvoke(InvocationInfo info)
    {
        Console.WriteLine(">>Intercepting " + info.TargetMethod.Name);
    }
    public object DoInvoke(InvocationInfo info)
    {
        return info.TargetMethod.Invoke(this._target, info.Arguments);
    }
    public void AfterInvoke(InvocationInfo info, object returnValue)
    {
        Console.WriteLine("<<Intercepted " + info.TargetMethod.Name + ", result: " + (returnValue == null ? "null" : returnValue.ToString()));
    }
}

使用代码:

ProxyFactory factory = new ProxyFactory();
SimpleSamepleEntity entity = new SimpleSamepleEntity() { Name = "Richie", Age = 99 };
SimpleSampleInterceptor interceptor = new SimpleSampleInterceptor(entity);
SimpleSamepleEntity proxy1 = factory.CreateProxy<SimpleSamepleEntity>(interceptor);
Console.WriteLine(proxy1.Name);
Console.WriteLine(proxy1.ToString());
Console.WriteLine("==============================");
SimpleSampleWrapper wrapper = new SimpleSampleWrapper(entity);
SimpleSamepleEntity proxy2 = factory.CreateProxy<SimpleSamepleEntity>(wrapper);
Console.WriteLine(proxy2.Name);
Console.WriteLine(proxy2.ToString());
Console.ReadKey();

运行结果:
   

说明:
1. LinFu的Dynamic Proxy有2种方式实现拦截器,即上面示例的IInterceptor和IInvokeWrapper接口
2. 与Castle Dynamic Proxy的不同之处在于,LinFu的拦截器只负责拦截功能,他并不维护目标真实对象,所以表现出来的差异有:
    a). 在拦截器接口中没有类似Castle的invocation.Proceed类似的方法,因为LinFu根本不知道目标真实对象在哪里。上面示例中我们在IInterceptor和IInvokeWrapper构造器中传入了目标对象,在拦截器接口方法中在_target对象上调用目标方法
    b). Castle在创建class proxy的时候,如果没有提供target,Castle会自己创建一个目标实体对象。而LinFu将interceptor与目标对象分离,所以在创建代理对象的时候不会创建目标对象
    c). 可以这样理解,LinFu的代理对象与Castle的interface proxy without target的行为基本一致。如果使用者也不处理target,则代理对象仅仅是一个拦截器,比Castle的class proxy要简洁
3. LinFu不像Castle,将proxy分为class proxy、interface proxy等类型,在LinFu中这些概念对使用者是透明的,但这里面也有些方面值得注意:
    a). 如果创建的是class proxy,则只能对virtual的方法进行拦截;如果创建的是interface proxy,非virtual的方法也可以实现拦截,这一点与Castle是一致的
    b). 如果创建的是interface proxy,即使目标对象override了ToString等方法,LinFu也无法通过info.TargetMethod.Invoke调用到目标对象的ToString方法
4. 拦截机制上的差异
    上面示例中,SimpleSamepleEntity的ToString方法中还调用了this.Name、this.Age,在Castle中这2个调用可以被拦截到,但LinFu中只能拦截到ToString方法

LinFu的代理对象都实现了IProxy接口,可以通过IProxy接口动态改变拦截器。比如上面的例子中,再实现一个拦截器:

public class AnotherInterceptor : IInterceptor
{
    public object Intercept(InvocationInfo info)
    {
        Console.WriteLine(">>Intercepting " + info.TargetMethod.Name);
        return null;
    }
}
ProxyFactory factory = new ProxyFactory();
SimpleSamepleEntity entity = new SimpleSamepleEntity() { Name = "Richie", Age = 99 };
SimpleSampleInterceptor interceptor = new SimpleSampleInterceptor(entity);
SimpleSamepleEntity proxy = factory.CreateProxy<SimpleSamepleEntity>(interceptor);
Console.WriteLine("name: " + proxy.Name);
Console.WriteLine("entity: "+proxy.ToString());
AnotherInterceptor interceptor2 = new AnotherInterceptor();
(proxy as IProxy).Interceptor = interceptor2;
Console.WriteLine("name: " + proxy.Name);
Console.WriteLine("entity: " + proxy.ToString());
Console.ReadKey();

性能对比:
下图是作者做的一个与Castle DP的性能对比测试,都禁用掉了缓存,创建不同类型的代理对象。横轴是创建代理对象的个数,纵轴是所花的时间
   

准备看一下LinFu的DynamicObject、IoC,但这2个功能只在1.0的版本中才有,在后来新的LinFu.Core.dll、LinFu.DynamicProxy.dll程序集的基础上没法使用。github中最新的代码里面也没有DynamicObject这个对象,作者还在修改

参考:
Introducing the LinFu Framework, Part I - LinFu.DynamicProxy: A Lightweight Proxy Generator
Introducing the LinFu Framework, Part II: LinFu.DynamicObject – Adding Dynamic Language Features to Statically Typed Languages
Introducing the LinFu Framework, Part III: LinFu.Delegates-Lambda Arguments & Universal Event Handling
Introducing the LinFu Framework, Part IV: Simple.IOC – The Five Minute Inversion of Control Container
Introducing the LinFu, Part V: LinFu.DesignByContract2 – Adding Transparent Design by Contract Features to Any .NET Language
Introducing LinFu, Part VI: LinFu.AOP – Pervasive Method Interception and Replacement for Sealed Types in Any .NET Language

抱歉!评论已关闭.