Динамический прокси-сервер 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 был перехвачен при вызове из программы, но не изнутри 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 via обертка с использованием текущего кода создания прокси-сервера, вам нужно будет сообщить существующий объект об оболочке, либо как поле внутри нее, либо как параметр метода.

кроме того, может быть другой способ создания прокси-сервера для начала - тот, где прокси is в некотором смысле целевой объект. Подозреваю, вы захотите взглянуть на CreateClassProxy, а не CreateClassProxyWithTarget - Я подозреваю, что это тот факт, что вы поставляет объект, который вызывает у вас проблемы.

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