Castle Dynamic Proxy не перехватывает вызовы методов при вызове из класса - PullRequest
12 голосов
/ 09 июля 2011

При использовании 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

Насколько я могу судить, динамический прокси-сервер способен только на вызовы прокси-методов, если вызов поступает извне самого класса, так как метод2 был перехвачен при вызове изПрограмма, но не из InterceptedClass.

Я могу отчасти понять, что при совершении вызовов из прокси-класса он больше не будет проходить через прокси-сервер, а просто хотел проверить, что это ожидалось, и, если это так, посмотреть, есть ли там вообщеполучить все перехваченные вызовы независимо от того, откуда они вызваны?

Спасибо

1 Ответ

16 голосов
/ 09 июля 2011

EDIT: 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 - я подозреваю, что это факт, что вы поставляете целевой объект, который вызывает у вас проблемы.

Является ли поведение, которое вы видите, «ожидаемым» или нет, очевидно, зависит от ваших ожиданий - но это, безусловно, то, чего ожидал бы I , ничего не зная о Castle Dynamic Proxy:)

...