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();
上面示例使用CreateClassProxy方法創建了一個代理對象entity,從圖中輸出的entity類型可以看到他的類型爲 Castle.Proxies.SimpleSampleEntity
當調用代理對象的任何方法時,將使用CallingLogInterceptor這個攔截器進行處理,在CallingLogInterceptor中輸出了調用日誌信息
在攔截器的接口方法Intercept中,可以修改入參,決定是否調用真實方法,修改返回結果等
可以攔截的方法:
1. 對於Class Proxy類型的代理,因爲DP使用繼承和override虛方法的方式實現代理,所以被攔截的方法必須爲virtual類型,非virtual類型的方法無法攔截
2. 實體繼承自Object、MarshalByRefObject等對象的方法,如果在實體類中沒有override將無法攔截
DP會將動態創建的代理類型緩存起來