16

Castle の Dynamic Proxy を使用しているときに、少し (私が思うに) 奇妙な動作に遭遇しました。

次のコードを使用します。

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 と呼ばれる

私が知る限り、動的プロキシは、呼び出しがクラス自体の外部から来た場合にのみメソッド呼び出しをプロキシできます。これは、Program から呼び出されたときに Method2 がインターセプトされたが、InterceptedClass 内からではなかったからです。

プロキシされたクラス内から呼び出しを行うと、プロキシを通過しなくなることはある程度理解できますが、これが予想されていたことを確認したかっただけで、そうであれば、とにかくすべての呼び出しをインターセプトする方法があるかどうかを確認したかっただけです。彼らはどこから呼ばれていますか?

ありがとう

4

1 に答える 1

19

編集: 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);

私が理解しているように、プロキシ ジェネレーターは効果的にラッパー オブジェクトを作成しています。それらは 2 つの別個のオブジェクトです。一方は他方の単なるラッパーであり、ラッパー レイヤーにインターセプトなどがあります。

のインスタンスが独自のメソッド呼び出しで行ったことをどのように変更できるかを理解するのは困難です。InterceptedClass

  • DynamicProxy は既存のオブジェクトの型を変更できません。オブジェクトが作成されると、そのタイプは固定されます
  • DynamicProxy は、既存のオブジェクトへの既存の呼び出しのバインド方法を変更できません

現在のプロキシ作成コードを使用してラッパー経由Method1で呼び出したい場合は、既存のオブジェクトに、その中のフィールドまたはメソッド パラメーターとして、ラッパーについて伝える必要があります。Method2

あるいは、最初にプロキシを作成する別の方法があるかもしれません - プロキシ何らかの意味でターゲットオブジェクトである場合。CreateClassProxyではなく、見たいと思うかもしれません-問題を引き起こしているのは、ターゲットオブジェクトを提供しCreateClassProxyWithTargetているという事実だと思います。

あなたが見ている動作が「期待される」かどうかは、明らかにあなたの期待に依存します - しかし、Castle Dynamic Proxyについて何も知らなくても、それは確かに私が期待するものです:)

于 2011-07-09T09:28:34.463 に答える