Замок Dynamic Proxy не перехватывает вызовы методов при вызове из класса

Я столкнулся с каким-то странным поведением при использовании 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

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

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

Спасибо

Ответ 1

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

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