为什么不会为* each * virtual方法调用调用DynamicProxy的拦截器?

一个例子最好地解释了:

public interface IA { void foo(); void bar(); } public class A : IA { public virtual void foo(){ Console.Write("foo"); bar(); //call virtual method } public virtual void bar(){ Console.Write("bar"); } } public class Interceptor : IInterceptor { public void Intercept(IInvocation invocation) { Console.WriteLine("Intercepted: " + invocation.Method.Name); invocation.Proceed(); } } Main(){ IA a = new A(); //proxy-ing an interface, given an implementation IA proxy = new Castle.DynamicProxy.ProxyGenerator() .CreateInterfaceProxyWithTarget(a, new Interceptor()); proxy.foo(); } 

我原本期望输出:

 Intercepted foo foo Intercepted bar bar 

相反,我得到:

 Intercepted foo foo bar 

为什么?

动态代理如何工作? 我期望生成的代理从代理类inheritance ,但是,似乎它使用组合将代理接口中的每个方法委托给实际的实现。

我尝试使用Castle DynamicProxy以及Cramon的旧动态代理实现

看起来我的猜测是正确的。

我尝试了同样的例子,这次只是直接从类类型创建代理:

 Main(){ //proxy-ing an explicit type A proxy = (A) new Castle.DynamicProxy.ProxyGenerator() .CreateClassProxy(new Interceptor()); proxy.foo(); } 

结果是我首先想到的:

 Intercepted foo foo Intercepted bar bar 

这导致我得出以下结论:

  • 从接口创建代理时,它使用组合来委托对实现的调用
  • 从(类)类型创建代理时,它inheritance自类型,因此类类型中的所有虚拟调用都将调用代理中的重写方法。

使用接口实现创建接口代理时,生成的代理看起来像这样:

 class InterfaceProxy: IA { //implements interface IA m_impl; [...] Proxy(IA i_impl){ m_impl = i_impl; } public void foo(){ //overly-simplified, but you get the picture InvokeInterceptors("foo"); //execution gets here when calling 'invocation.Proceed()' //from the interceptor m_impl.foo(); //pass the execution to the implementation; //the proxy has no more control over what gets executed. } public void bar(){ InvokeInterceptors("bar"); m_impl.bar(); } } 

创建类代理时,代码如下所示:

 class ClassProxy: A { //inherits class type Proxy(): base() { ... } public override void foo(){ InvokeInterceptors("foo"); //execution gets here when calling 'invocation.Proceed()' //from the interceptor base.foo(); //pass the execution to the base class } public void bar(){ InvokeInterceptors("bar"); base.bar(); } } 

您正在使用CreateInterfaceProxyWithTarget方法,该方法指示代理构建器为接口创建代理并将调用转发给目标对象,因此您所看到的就是您要求它执行的操作。

如果您希望代理从您的类派生,那么您需要使用CreateClassProxy方法。