为什么*每个*虚拟方法调用不会调用 DynamicProxy 的拦截器?

发布于 2024-08-19 10:12:22 字数 1062 浏览 11 评论 0原文

一个例子最好地解释了这一点:

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

An example explains it best :

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();

}

I would have expected the output:

Intercepted foo
foo
Intercepted bar
bar

Instead, I get:

Intercepted foo
foo
bar

Why?

How does the dynamic proxy work?
I was expecting the generated proxy to inherit from the proxied class, however, it seems that it uses composition to delegate each of the methods in the proxied interface to the actual implementation.

I've tried with Castle DynamicProxy and also with an older dynamic proxy implementation, from Cramon

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明媚如初 2024-08-26 10:12:22

看来我的猜测是对的。

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

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();
  }
}

Looks like my guess was right.

I tried the same example, only this time creating the proxy directly from the class type:

Main(){

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

}

The result was what I expected in the first place:

Intercepted foo
foo
Intercepted bar
bar

This leads me to the following conclusion:

  • when creating a proxy from an interface, it uses composition to delegate calls to the implementation
  • when creating a proxy from a (class) type, it inherits from the type, so all virtual calls in the class type will call the overridden methods in the proxy.

When creating an interface proxy with an interface implementation, the generated proxy looks something like this:

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();
  }
}

When creating a class proxy, the code looks like this:

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();
  }
}
怀念你的温柔 2024-08-26 10:12:22

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

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

You're using the method CreateInterfaceProxyWithTarget which instructs the proxy builder to create a proxy for the interface and forward the calls to the target object, so what you're seeing is what you've asked it to do.

If you want the proxy to derive from your class then you'd need to use the CreateClassProxy method instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文