2010-10-31 5 views
5

J'essaie de gérer un appel d'une méthode générique à travers un RealProxy, mais je n'arrive pas à trouver les informations sur le type réel du paramètre générique utilisé dans l'appel de méthode intercepté. Un extrait du code:C# RealProxy: méthodes génériques?

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); 
     ... 

Disons que je suis mandatement une interface comme

interface IFactory 
{ 
    TService Create<TService>() 
} 

Quand j'appelle le proxy

proxied.Create<MyClass>() 

Je veux être en mesure de trouver la le paramètre générique est de type MyClass. Est-ce possible grâce à RealProxy?

+0

Il est possible par réflexion pour interroger les types génériques. – fhj

+0

Essayer de trouver la classe générique exacte va un peu à l'encontre du but d'avoir une classe générique. Pourquoi avez-vous besoin de connaître la classe? –

+0

@Albin, j'écris un proxy de méthode d'usine pour un cadre d'injection de dépendance sur lequel je travaille. Quelque chose comme installation d'usine typée de Windsor (http://kozmic.pl/archive/2009/12/24/castle-typed-factory-facility-reborn.aspx) –

Répondre

6

Il ya un excellent MSDN article sur RealProxy que je vous recommande de lire. Entre autres choses, il introduit MethodCallMessageWrapper, ce qui vous évite de travailler directement avec le dictionnaire Properties. De ce dernier, vous pouvez obtenir le MethodBase, qui à son tour contient les arguments génériques:

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

Grand, il me manquait le code de l'emballage, merci! –

+0

Pas de problème! Je vous recommande quand même de lire l'article, c'est vraiment bon –

+0

Dommage que le lien soit cassé! – Guge

3

Pour les appels de méthode, l'argument IMessage devrait être un IMethodMessage, qui possède une propriété MethodBase:

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, j'ai testé votre code et cela fonctionne, merci, +1. Je suis désolé de ne pas pouvoir accepter les deux réponses. –

+1

Puisque 'IMethodCallMessage' implémente' IMethodMessage', et 'MethodCallMessageWrapper' est un simple wrapper pour' IMethodCallMessage', nos deux réponses se réduisent à peu près au même code –

Questions connexes