Castle 系列: Castle DynamicProxy动态生成透明代理类型
2012-04-19 11:48
381 查看
Castle DynamicProxy动态生成透明代理类型,实体不需要继承MarshalByRef、ContextBoundObject便可以实现代理类
基于透明代理的功能,可以实现对方法调用的拦截处理,例如NHibernate用它实现延迟加载
DP的使用非常简单,内部没有使用反射,而是采用Emit、委托等方式生成代理类型,调用真实类的方法,性能方面也没有太多损失
基本示例
引用的命名空间:
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
被代理的实体类:
public class 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 CallingLogInterceptor : IInterceptor
{
private int _indent = 0;
private void PreProceed(IInvocation invocation)
{
if (this._indent > 0)
Console.Write(" ".PadRight(this._indent * 4, ' '));
this._indent++;
Console.Write("Intercepting: " + invocation.Method.Name + "(");
if (invocation.Arguments != null && invocation.Arguments.Length > 0)
for (int i = 0; i < invocation.Arguments.Length; i++)
{
if (i != 0) Console.Write(", ");
Console.Write(invocation.Arguments == null
? "null"
: invocation.Arguments.GetType() == typeof(string)
? "\"" + invocation.Arguments.ToString() + "\""
: invocation.Arguments.ToString());
}
Console.WriteLine(")");
}
private void PostProceed(IInvocation invocation)
{
this._indent--;
}
public void Intercept(IInvocation invocation)
{
this.PreProceed(invocation);
invocation.Proceed();
this.PostProceed(invocation);
}
}
复制代码测试代码:
ProxyGenerator generator = new ProxyGenerator();
CallingLogInterceptor interceptor = new CallingLogInterceptor();
SimpleSamepleEntity entity = generator.CreateClassProxy<SimpleSamepleEntity>(interceptor);
entity.Name = "Richie";
entity.Age = 50;
Console.WriteLine("The entity is: " + entity);
Console.WriteLine("Type of the entity: " + entity.GetType().FullName);
Console.ReadKey();
复制代码运行结果:
dynamic-proxy-sample-1.JPG(19.01
K)
3/22/2010 12:06:06 AM
上面示例使用CreateClassProxy方法创建了一个代理对象entity,从图中输出的entity类型可以看到他的类型为 Castle.Proxies.SimpleSampleEntity
当调用代理对象的任何方法时,将使用CallingLogInterceptor这个拦截器进行处理,在CallingLogInterceptor中输出了调用日志信息
在拦截器的接口方法Intercept中,可以修改入参,决定是否调用真实方法,修改返回结果等
可以拦截的方法:
1. 对于Class Proxy类型的代理,因为DP使用继承和override虚方法的方式实现代理,所以被拦截的方法必须为virtual类型,非virtual类型的方法无法拦截
2. 实体继承自Object、MarshalByRefObject等对象的方法,如果在实体类中没有override将无法拦截
DP会将动态创建的代理类型缓存起来
基于透明代理的功能,可以实现对方法调用的拦截处理,例如NHibernate用它实现延迟加载
DP的使用非常简单,内部没有使用反射,而是采用Emit、委托等方式生成代理类型,调用真实类的方法,性能方面也没有太多损失
基本示例
引用的命名空间:
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
被代理的实体类:
public class 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 CallingLogInterceptor : IInterceptor
{
private int _indent = 0;
private void PreProceed(IInvocation invocation)
{
if (this._indent > 0)
Console.Write(" ".PadRight(this._indent * 4, ' '));
this._indent++;
Console.Write("Intercepting: " + invocation.Method.Name + "(");
if (invocation.Arguments != null && invocation.Arguments.Length > 0)
for (int i = 0; i < invocation.Arguments.Length; i++)
{
if (i != 0) Console.Write(", ");
Console.Write(invocation.Arguments == null
? "null"
: invocation.Arguments.GetType() == typeof(string)
? "\"" + invocation.Arguments.ToString() + "\""
: invocation.Arguments.ToString());
}
Console.WriteLine(")");
}
private void PostProceed(IInvocation invocation)
{
this._indent--;
}
public void Intercept(IInvocation invocation)
{
this.PreProceed(invocation);
invocation.Proceed();
this.PostProceed(invocation);
}
}
复制代码测试代码:
ProxyGenerator generator = new ProxyGenerator();
CallingLogInterceptor interceptor = new CallingLogInterceptor();
SimpleSamepleEntity entity = generator.CreateClassProxy<SimpleSamepleEntity>(interceptor);
entity.Name = "Richie";
entity.Age = 50;
Console.WriteLine("The entity is: " + entity);
Console.WriteLine("Type of the entity: " + entity.GetType().FullName);
Console.ReadKey();
复制代码运行结果:
dynamic-proxy-sample-1.JPG(19.01
K)
3/22/2010 12:06:06 AM
上面示例使用CreateClassProxy方法创建了一个代理对象entity,从图中输出的entity类型可以看到他的类型为 Castle.Proxies.SimpleSampleEntity
当调用代理对象的任何方法时,将使用CallingLogInterceptor这个拦截器进行处理,在CallingLogInterceptor中输出了调用日志信息
在拦截器的接口方法Intercept中,可以修改入参,决定是否调用真实方法,修改返回结果等
可以拦截的方法:
1. 对于Class Proxy类型的代理,因为DP使用继承和override虚方法的方式实现代理,所以被拦截的方法必须为virtual类型,非virtual类型的方法无法拦截
2. 实体继承自Object、MarshalByRefObject等对象的方法,如果在实体类中没有override将无法拦截
DP会将动态创建的代理类型缓存起来
相关文章推荐
- Castle 系列:Castle DynamicProxy动态生成透明代理类型详解
- 解决spring使用动态代理类型转换失败的问题--java.lang.ClassCastException: com.sun.proxy.$Proxy$ cannot be cast to ...
- Dynamic Proxy (动态代理模式)
- 解决spring使用动态代理类型转换失败的问题--java.lang.ClassCastException: com.sun.proxy.$Proxy$ cannot be cast to ...今天
- .Net动态代理Castle系列(二)--- ORM中延迟加载及实现
- Spring Dynamic Proxy (AOP动态代理的实现)
- 解决Proxy.newProxyInstance创建动态代理导致类型转换错误的问题
- 基于Autofac, Castle.DynamicProxy的动态WCF解决方案(原创)
- .Net动态代理Castle系列
- Design Pattern—— Dynamic Proxy Pattern 动态代理模式
- 使用反射生成JDK动态代理---使用Proxy和InvocationHandler创建动态代理
- java dynamic proxy,动态代理
- Java事务(6)——使用动态代理(Dynamic Proxy)
- dubbo源码之动态代理模式生成proxy过程
- .Net动态代理Castle系列
- Cglib Dynamic Proxy(Cglib 动态代理)
- DynamicProxy(动态代理)技术剖析(2)
- spring框架Proxy-代理模式(动态生成代理对象)
- Design Pattern—— Dynamic Proxy Pattern(三) 动态代理模式
- 设计模式之五S:动态代理模式(Dynamic Proxy Pattern)