【问题标题】:Castle Dynamic Proxy not intercepting method calls when invoked from within the class从类中调用时,Castle Dynamic Proxy 不拦截方法调用
【发布时间】:2011-10-01 19:29:29
【问题描述】:

在使用 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
  • 调用方法1
  • 拦截调用:Method2
  • 调用方法2
  • 拦截调用:Method2
  • 调用方法2

然而我得到的是:

  • 拦截调用:Method1
  • 调用方法 1
  • 调用方法2
  • 拦截调用:Method2
  • 调用方法2

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

我可以理解,当从代理类中进行调用时,它将不再通过代理,但只是想检查这是否是预期的,如果是,那么看看是否有任何方法可以获取所有调用无论从哪里调用都被拦截?

谢谢

【问题讨论】:

    标签: c# castle-dynamicproxy dynamic-proxy


    【解决方案1】:

    编辑: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 通过包装器,您需要告诉现有对象有关包装器的信息,或者作为其中的一个字段或作为方法参数。

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

    您所看到的行为是否是“预期的”显然取决于您的预期 - 但这肯定是 所期望的,但对 Castle Dynamic Proxy 一无所知 :)

    【讨论】:

    • 是的,我想的差不多。所以换句话说,对“cp”的调用可以被拦截,而对“c”的调用不能,这包括从“c”内部对“c”的调用——这并不奇怪。顺便说一句:我可能应该考虑在提问时使用更具描述性的变量名称,嗯?
    • 感谢您的更新 - 使用 CreateClassProxyWithTarget 的原因是,在实际问题中,我试图解决的目标对象是由 IoC 容器创建的,然后我想用代理包装它。但是这个特定的问题不在这个问题的范围内。感谢您的帮助。
    • @George:有什么方法可以说服 IoC 容器使用 Castle Dynamic Proxy 本身吗?正如你所说,它与这个问题略有不同,但它可能是可行的......
    猜你喜欢
    • 2011-10-03
    • 1970-01-01
    • 2018-01-30
    • 2012-06-01
    • 2018-02-05
    • 2011-09-30
    • 1970-01-01
    • 2014-10-11
    相关资源
    最近更新 更多