12

一个例子最好地解释它:

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

为什么?

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

我已经尝试过 Castle DynamicProxy 以及Cramon的旧动态代理实现

4

2 回答 2

14

看来我的猜测是对的。

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

Main(){

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

}

结果是我一开始所期望的:

Intercepted foo
foo
Intercepted bar
bar

这使我得出以下结论:

  • 从接口创建代理时,它使用组合将调用委托给实现
  • 从(类)类型创建代理时,它继承自该类型,因此类类型中的所有虚拟调用都会调用代理中覆盖的方法。

使用接口实现创建接口代理时,生成的代理如下所示:

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();
  }
}
于 2010-01-28T09:39:10.707 回答
8

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

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

于 2010-01-28T09:00:56.457 回答