LinFu Dynamic Proxy - LinFu 2.3, LinFu.DynamicProxy 1.031
项目地址:Google Code,GitHub
实现的特性有:
1. AOP
2. Dynamic Proxy
3. Minxins
4. Duck Typing
5. Design by Contract
基本示例
说明:
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接口动态改变拦截器。比如上面的例子中,再实现一个拦截器:
下图是作者做的一个与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
实现的特性有:
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