2011-07-09 12 views
10

Podczas korzystania z Dynamic Proxy Castle natknąłem się na pewne (jak sądzę) dziwne zachowanie.Castle Dynamic Proxy nie przechwytuje wywołań metod po wywołaniu z klasy

z następującego kodu:

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"); 
    } 
} 

Spodziewałem się uzyskać wynik:

  • przechwycone wezwanie do: method1
  • zwana metoda 1
  • przechwycone wywołanie: Method2
  • Metoda nazwana 2
  • przechwycone wywołanie: Method2
  • zwana metoda 2

Jednak Dostałem:

  • przechwycone wywołanie: method1
  • zwana metoda 1
  • zwana metoda 2
  • Przechwycone połączenie z: Method2
  • Metoda nazwana 2

O ile wiem, dynamiczny serwer proxy może wywoływać tylko metody proxy, jeśli wywołanie pochodzi spoza samej klasy, ponieważ metoda 2 została przechwycona podczas wywoływania z Programu, ale nie z poziomu InterceptedClass.

Mogę zrozumieć, że podczas wykonywania połączeń z poziomu klasy pośredniczącej nie będzie już przechodzić przez serwer proxy, ale po prostu chciał sprawdzić, czy było to oczekiwane, a jeśli jest, to sprawdź, czy jest i tak, aby uzyskać wszystkie połączenia przechwytywane bez względu na to skąd są wywoływane?

Dzięki

Odpowiedz

15

EDIT: tl; dr - Właśnie próbowałem tworzenia pełnomocnictwa w inny sposób, jak opisano poniżej, a to powoduje wyjście byłaś po. Po prostu musiałem to zmienić:

var c = new InterceptedClass(); 
var i = new Interceptor(); 

var cp = new ProxyGenerator().CreateClassProxyWithTarget(c, i); 

do tego:

var i = new Interceptor(); 
var cp = new ProxyGenerator().CreateClassProxy<InterceptedClass>(i); 

Jak rozumiem, generator proxy jest skutecznie tworząc obiekt otoki. Są to dwa oddzielne obiekty - jeden jest po prostu opakowaniem wokół drugiego, z przechwytywaniem itp. W warstwie owijki.

Trudno, aby zobaczyć jak to mogło zmieniać co instancja InterceptedClass zrobił z wywołuje własną metodę:

  • DynamicProxy nie może zmienić typ istniejącego obiektu; Po utworzeniu obiektu, jego typ jest stała
  • DynamicProxy nie można zmienić w jaki sposób istniejące połączenia do istniejącego obiektu zobowiązane są

Jeśli chcesz Method1 zadzwonić Method2poprzez opakowanie użyciu bieżącego tworzenia proxy kod, musisz powiedzieć istniejącemu obiektowi o opakowaniu, albo jako pole w nim, albo jako parametr metody.

Alternatywnie, może istnieć inny sposób tworzenia proxy na początek - jeden, w którym proxy jest w pewnym sensie obiektem docelowym. Podejrzewam, że możesz chcieć spojrzeć na CreateClassProxy zamiast CreateClassProxyWithTarget - podejrzewam, że jest to fakt, że jesteś dostarczając obiekt docelowy, który powoduje problemy.

czy zachowanie widzisz jest „oczekiwany”, czy nie zależy oczywiście od twoich oczekiwań - ale to z pewnością co I spodziewałbym się, nie wiedząc nic o Zamek Dynamiczna Proxy :)

+0

Tak, ja niby wymyślił tyle. Innymi słowy, połączenia z "cp" mogą być przechwytywane, a wywołania "c" nie mogą obejmować wywołań "c" z "c" - co wcale nie jest zaskakujące. Na marginesie: powinienem pomyśleć o użyciu nieco bardziej opisowych nazw zmiennych podczas zadawania pytań, co? –

+0

Dzięki za aktualizację - powodem użycia CreateClassProxyWithTarget jest to, że w rzeczywistym problemie, który próbuję rozwiązać, obiekt docelowy jest tworzony przez kontener IoC, który następnie chcę zawinąć z serwerem proxy. Ale ten konkretny problem leży poza zakresem tego pytania. Dzięki za pomoc. –

+0

@George: Czy jest jakiś sposób, aby przekonać kontener IoC do korzystania z Castle Dynamic Proxy? Jak mówisz, jest to nieco oddzielne od tego pytania, ale może być wykonalne ... –

Powiązane problemy