您的位置:首页 > 其它

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会将动态创建的代理类型缓存起来
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: