2010-10-31 16 views
5

Estoy tratando de manejar una llamada de un método genérico a través de un RealProxy, pero parece que no puedo encontrar la información sobre el tipo real del parámetro genérico utilizado en la llamada al método interceptado. Un extracto del código:C# RealProxy: métodos genéricos?

public override IMessage Invoke(IMessage msg) 
    { 
     ... 
     string methodName = (string)msg.Properties["__MethodName"]; 
     Type[] parameterTypes = (Type[])msg.Properties["__MethodSignature"]; 
     object[] args = (object[])msg.Properties["__Args"]; 

     MethodInfo method = typeToProxy.GetMethod(methodName, parameterTypes); 
     ... 

Digamos que estoy proxy a una interfaz como

interface IFactory 
{ 
    TService Create<TService>() 
} 

Cuando llamo el proxy

proxied.Create<MyClass>() 

Quiero ser capaz de averiguar la parámetro genérico es del tipo MyClass. ¿Es esto posible a través del RealProxy?

+0

Es posible a través de la reflexión para consultar tipos genéricos. – fhj

+0

Intentar averiguar la clase genérica exacta en cierto modo frustra el propósito de tener una clase genérica. ¿Por qué necesitas saber la clase? –

+0

@Albin, estoy escribiendo un proxy de método de fábrica para un marco de inyección de dependencia en el que estoy trabajando. Algo parecido a las instalaciones de fábrica mecanografiadas de Windsor (http://kozmic.pl/archive/2009/12/24/castle-typed-factory-facility-reborn.aspx) –

Respuesta

6

Hay un excelente MSDN article sobre RealProxy que recomiendo leer. Entre otras cosas, introduce MethodCallMessageWrapper que le ahorra la molestia de trabajar directamente en contra del diccionario Properties. De este último se puede obtener el MethodBase, que a su vez contiene los argumentos genéricos:

internal class MyProxy : RealProxy 
{ 
    private object m_instance;  
    private MyProxy(object instance) : base(typeof(IFactory)) 
    { 
     m_instance = instance; 
    } 

    public override IMessage Invoke(IMessage message) 
    { 
    IMethodCallMessage methodMessage = 
     new MethodCallMessageWrapper((IMethodCallMessage) message); 

    // Obtain the actual method definition that is being called. 
    MethodBase method = methodMessage.MethodBase; 

    Type[] genericArgs = method.GetGenericArguments(); //This is what you want 

    return new ReturnMessage(...); 
    } 

    ... 
} 
+0

Genial, me faltaba el código de envoltura, ¡gracias! –

+0

¡Ningún problema! Aun así, recomiendo que leas el artículo, es realmente bueno –

+0

¡Qué mal que el enlace esté roto! – Guge

3

Para las llamadas de método, el argumento IMessage debe ser un IMethodMessage, que tiene una MethodBase propiedad:

public override IMessage Invoke(IMessage message) 
{ 
    IMethodMessage methodMessage = message as IMethodMessage; 
    if (methodMessage != null) 
    { 
     MethodBase method = methodMessage.MethodBase; 
     Type[] genericArgs = method.GetGenericArguments(); 

     ... 
    } 
    else 
    { 
     // not a method call 
    } 
} 
+0

Ruben, probé tu código y funciona, gracias, +1. Lo siento, no pude aceptar ambas respuestas. –

+1

Dado que 'IMethodCallMessage' implementa' IMethodMessage', y 'MethodCallMessageWrapper' es un contenedor simple para' IMethodCallMessage', ambas respuestas se reducen a prácticamente el mismo código –