2010-06-24 14 views
1

Laissez-moi essayer de donner un petit exemple.MethodInfo.Invoke avec un délégué dans Object [] params

class Session (
    public delegate string CleanBody(); 
    public static void Execute(string name, string q, CleanBody body) ... 

peut être utilisé comme:

Session.Execute("foo", "bar", delegate() { string x="beep"; /* whatever*/ return x; }); 

Mais si je dois courir est par MethodInfo.Invoke - comme dans différents dll aucun type de dépendances de toute façon. Comme:

Type type = Type.GetType("Bla.Session, FooSessionDll", true); 
MethodInfo methodInfo = type.GetMethod("Execute"); 

Object [] args = { "foo", "bar", delegate() // Doesn't compile, now that ? 
{ 
    string x="beep"; /* whatever*/ return x; 
} 

methodInfo.Invoke("Trial Execution :-)", args); 

Quelle que soit astuce/cast serait appliqué devrait être telle qu'elle arrive toujours à exécuter en tant que délégué véritable. délégué réel (s) peut avoir des signatures plus complexes, etc., etc.

+0

S'il vous plaît expliquer avec plus de détails pourquoi vous voulez faire une telle chose déroutante. Il pourrait y avoir un meilleur moyen. – ChaosPandion

+0

Malheureusement, il n'y a pas beaucoup de marge de manœuvre pour le casting de type avec les délégués. Je devrais d'abord remettre en question l'architecture générale. Sans un raisonnement clair, certaines questions peuvent ne pas avoir de bonne réponse. – SamuelWarren

+0

Il n'y a rien de déroutant à ce sujet - juste essayer de répliquer par reclection l'appel exact qu'il pourrait faire s'il prenait la dépendance de type. C'est tout. Il y a quelques classes spécilazed dans CLR qui font un "enveloppement" très limité des délégués dans les classes Object-compat - j'ai juste besoin d'une variante plus générale de la même. Le pointeur B (Session.Execute) est un énorme paquet lageacy qui a encore des "clients" parmi les DLL chargées par le côté A (en faisant MethodInfo.Invoke). – ZXX

Répondre

0

OK, a trouvé la solution: Func<<TResult>>, et toute la famille des modèles Func. En ce qui concerne l'exemple que j'ai posté, la conversion de la signature d'exécution (...) à:

public static void Execute(string name, string q, Func<string> body) 

est fonctionnellement équivalent à celui qui a délégué explicitement nommé à-dire tout code prenant la dépendance de type sur elle peut encore utiliser

Session.Execute("foo", "bar", delegate() { ... }); 

avec zéro changement de code, et tout dll indépendant peut maintenant faire:

Func<string> d = delegate() { .....} 

et le transmettre dans un Object[] comme argument normal.

Il y avait un autre thread demande « Qu'est-ce si grand sur Func<> » - Eh bien, c'est :-)

Il permet briser les dépendances et déchirages contre nature avec zéro changement de code pour le code existant qui l'utilise. Une condition est que le code existant utilise des méthodes anonymes (comme dans l'exemple) et non une création explicite de délégué à l'ancienne.

0
private static class Invoker 
{ 
    private static string Method() 
    { 
     return "beep"; 
    } 

    public static object Invoke() 
    { 
     Type type = Type.GetType("Bla.Session, FooSessionDll", true); 
     MethodInfo methodInfo = type.GetMethod("Execute"); 
     Type delegateType = methodInfo.GetParameters()[2].ParameterType; 
     Delegate delegateInstance = Delegate.CreateDelegate(delegateType, typeof(Invoker).GetMethod("Method")); 
     object[] args = new object[] { "foo", "bar", delegateInstance }; 
     return methodInfo.Invoke(null, args); 
    } 
} 
+0

Cela injecterait une dépendance de type à partir de cette DLL "autre". Ce n'est pas une question académique :-) dll A (using Invoke) devrait conpiler et courir même si dll B (avec Session.Execute) n'existe pas du tout. Quelque chose avec des types anonymes peut-être? – ZXX

+0

@zb_z - Je pense que cela peut vous aider, même si votre question n'est pas très claire. – ChaosPandion

+0

Hmm, que methodInfo.GetParameters() [2] .ParameterType semble prometteur, s'il y aurait un moyen de lancer delegate() {....}. Le délégué réel impliqué utilise un certain nombre d'objets de sa fermeture, donc ce n'est pas exactement remplaçable par une méthode statique, à moins que nous ayons guéri ce que nous n'avons pas :-) – ZXX