Castle 动态代理在从类内部调用时不会拦截方法调用

发布于 2024-11-19 00:05:08 字数 1352 浏览 3 评论 0原文

在使用 Castle 的动态代理时,我遇到了一些(我认为是)奇怪的行为。

使用以下代码:

class Program
{
    static void Main(string[] args)
    {
        var c = new InterceptedClass();
        var i = new Interceptor();

        var cp = new ProxyGenerator().CreateClassProxyWithTarget(c, i);

        cp.Method1();
        cp.Method2();

        Console.ReadLine();
    }
}

public class Interceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine(string.Format("Intercepted call to: " + invocation.Method.Name));

        invocation.Proceed();
    }
}

public class InterceptedClass
{
    public virtual void Method1()
    {
        Console.WriteLine("Called Method 1");
        Method2();
    }

    public virtual void Method2()
    {
        Console.WriteLine("Called Method 2");
    }
}

我期望得到输出:

  • 拦截的调用: Method1
  • Called Method 1
  • 拦截的调用: Method2
  • Called Method 2
  • 拦截的调用: Method2
  • Called Method 2

但是我得到的是:

  • 拦截的调用: Method1
  • Called Method 1
  • 被调用方法 2
  • 截获对以下对象的调用: Method2
  • 被调用方法 2

据我所知,动态代理只能代理方法调用(如果调用来自类本身外部) Method2 在从 Program 调用时被拦截,但不是从 InterceptedClass 中调用。

我可以理解,当从代理类中进行调用时,它将不再通过代理,而只是想检查这是否是预期的,如果是的话,看看是否有无论如何都可以拦截所有调用,无论他们从哪里被召唤?

谢谢

I have run into a bit of (what I think is) strange behaviour when using Castle's Dynamic Proxy.

With the following code:

class Program
{
    static void Main(string[] args)
    {
        var c = new InterceptedClass();
        var i = new Interceptor();

        var cp = new ProxyGenerator().CreateClassProxyWithTarget(c, i);

        cp.Method1();
        cp.Method2();

        Console.ReadLine();
    }
}

public class Interceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine(string.Format("Intercepted call to: " + invocation.Method.Name));

        invocation.Proceed();
    }
}

public class InterceptedClass
{
    public virtual void Method1()
    {
        Console.WriteLine("Called Method 1");
        Method2();
    }

    public virtual void Method2()
    {
        Console.WriteLine("Called Method 2");
    }
}

I was expecting to get the output:

  • Intercepted call to: Method1
  • Called Method 1
  • Intercepted call to: Method2
  • Called Method 2
  • Intercepted call to: Method2
  • Called Method 2

However what I got was:

  • Intercepted call to: Method1
  • Called Method 1
  • Called Method 2
  • Intercepted call to: Method2
  • Called Method 2

As far as I can tell then the dynamic proxy is only able to proxy method calls if the call comes from outside the class itself as Method2 was intercepted when called from Program but not from within InterceptedClass.

I can kind of understand that when making calls from within the proxied class it would no longer go through the proxy, but just wanted to check that this was expected and if it is then see if there is there anyway to get all calls intercepted regardless of where they're called from?

Thanks

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

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

发布评论

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

评论(1

风流物 2024-11-26 00:05:08

编辑:tl;dr - 我刚刚尝试以不同的方式创建代理,如下所述,它会生成您想要的输出。我只需更改此:

var c = new InterceptedClass();
var i = new Interceptor();

var cp = new ProxyGenerator().CreateClassProxyWithTarget(c, i);

对此:

var i = new Interceptor();
var cp = new ProxyGenerator().CreateClassProxy<InterceptedClass>(i);

据我了解,代理生成器实际上正在创建一个包装器对象。它们是两个独立的对象 - 一个只是另一个对象的包装器,在包装器层中进行拦截等。

很难看出它如何改变 InterceptedClass 实例通过其自己的方法调用所做的事情:

  • DynamicProxy 无法更改现有对象的类型;创建对象后,其类型是固定的
  • DynamicProxy 无法更改对现有对象的现有调用的绑定方式

如果您希望 Method1 调用 Method2 via< /em> 使用当前代理创建代码的包装器,您需要告诉现有对象有关包装器的信息,无论是作为其中的字段还是作为方法参数。

或者,可能有一种不同的方式来开始创建代理 - 代理在某种意义上是目标对象。我怀疑您可能想查看 CreateClassProxy 而不是 CreateClassProxyWithTarget - 我怀疑您正在提供目标对象,从而导致你的问题。

您所看到的行为是否是“预期”显然取决于您的期望 - 但这肯定是我所期望的,而不了解 Castle Dynamic Proxy :)

EDIT: tl;dr - I've just tried creating the proxy in a different way, as described below, and it produces the output you were after. I just had to change this:

var c = new InterceptedClass();
var i = new Interceptor();

var cp = new ProxyGenerator().CreateClassProxyWithTarget(c, i);

To this:

var i = new Interceptor();
var cp = new ProxyGenerator().CreateClassProxy<InterceptedClass>(i);

As I understand it, the proxy generator is effectively creating a wrapper object. They're two separate objects - one is just a wrapper around the other, with interception etc in the wrapper layer.

It's hard to see how it could change what the instance of InterceptedClass did with its own method calls:

  • DynamicProxy can't change the type of an existing object; once an object is created, its type is fixed
  • DynamicProxy can't change how existing calls to an existing object are bound

If you want Method1 to call Method2 via the wrapper using the current proxy creation code, you'll need to tell the existing object about the wrapper, either as a field within it or as a method parameter.

Alternatively, there may be a different way of creating the proxy to start with - one where the proxy is in some sense the target object. I suspect you may want to look at CreateClassProxy rather than CreateClassProxyWithTarget - I suspect it's the fact that you're supplying the target object which is causing you problems.

Whether the behaviour you're seeing is "expected" or not obviously depends on your expectations - but it's certainly what I would expect, without knowing anything about Castle Dynamic Proxy :)

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