2011-07-09 13 views
10

Me he encontrado con un comportamiento algo extraño (lo que creo que es) cuando uso el Dynamic Proxy de Castle.Castle Dynamic Proxy no intercepta llamadas de método cuando se invoca desde dentro de la clase

Con el siguiente código:

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

que estaba esperando para obtener la salida:

  • llamada interceptada a: Método1
  • llamado Método 1
  • llamada interceptada a: Método2
  • Método llamado 2
  • llamada interceptada a: Método2
  • llamado Método 2

Sin embargo, lo que me dieron fue:

  • llamada interceptada a: Método1
  • llamado Método 1
  • llamado Método 2
  • Llamada interceptada a: Método2
  • Método llamado 2

Por lo que puedo decir, el proxy dinámico solo puede realizar llamadas a métodos proxy si la llamada proviene de fuera de la clase como método interceptado cuando se llamó desde Program pero no desde InterceptedClass.

Puedo entender que al hacer llamadas desde dentro de la clase proxied ya no pasaría por el proxy, pero solo quería comprobar que esto era esperado y si es así, ver si hay alguna forma para obtener todo llamadas interceptadas independientemente de donde se llaman?

Gracias

Respuesta

15

EDIT: tl; dr - He intentado crear el proxy de una manera diferente, como se describe a continuación, y se produce la salida que fueron después. Sólo tenía que cambiar esta situación:

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

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

A esto:

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

Según tengo entendido, el generador de proxy está creando efectivamente un objeto envoltorio. Son dos objetos separados: uno es simplemente un envoltorio alrededor del otro, con intercepción, etc. en la capa de envoltura.

Es difícil ver cómo se podría cambiar lo que la instancia de InterceptedClass hizo con su propio método llama:

  • DynamicProxy no puede cambiar el tipo de un objeto existente; una vez que se crea un objeto, su tipo es fijo
  • DynamicProxy no puede cambiar la forma de las llamadas existentes a un objeto existente se une

Si desea Method1 llamar Method2 a través de la envoltura mediante la creación de proxy actual código, tendrá que decirle al objeto existente sobre el contenedor, ya sea como un campo dentro de él o como un parámetro de método.

Alternativamente, puede haber una forma diferente de crear el proxy para empezar, uno donde el proxy es en cierto sentido el objeto de destino. Sospecho que es posible que desee mirar CreateClassProxy en lugar de CreateClassProxyWithTarget - Sospecho que es el hecho de que está suministrando el objeto de destino que le está causando problemas.

si el comportamiento que se está viendo es "esperado" o no, obviamente, depende de sus expectativas - pero es ciertamente lo que esperaría, sin saber nada de Castillo dinámico Proxy :)

+0

Sí, me tipo de calculado tanto. Entonces, en otros términos, las llamadas a "cp" pueden interceptarse y las llamadas a "c" no pueden y eso incluye llamadas a "c" desde "c", lo que de ninguna manera es sorprendente. Como comentario adicional: probablemente debería pensar en usar nombres de variables ligeramente más descriptivos cuando haga preguntas, ¿eh? –

+0

Gracias por la actualización: la razón para usar CreateClassProxyWithTarget es que en el problema real que trato de resolver, el objeto de destino es creado por un contenedor IoC que luego quiero envolver con el proxy. Pero ese tema en particular está fuera del alcance de esta pregunta. Gracias por tu ayuda. –

+0

@George: ¿Hay alguna manera de convencer al contenedor IoC para que use Castle Dynamic Proxy? Como dices, está ligeramente separado de esta pregunta, pero puede ser factible ... –

Cuestiones relacionadas