2008-11-28 8 views
107

Éditer:Appel de la méthode générique avec un argument de type connu seulement à l'exécution

Bien sûr, mon vrai code ne ressemble pas exactement à ceci. J'ai essayé d'écrire du code semi-pseudo pour le rendre plus clair de ce que je voulais faire.

On dirait que ça a tout chamboulé à la place.

Alors, ce que je voudrais faire en fait est la suivante:

Method<Interface1>(); 
Method<Interface2>(); 
Method<Interface3>(); 
... 

Eh bien ... Je pensais que peut-être que je pourrais en faire une boucle en utilisant la réflexion. Donc, la question est: Comment comment puis-je le faire. J'ai très connaissance superficielle de la réflexion. Les exemples de code seraient donc géniaux.

Le scénario ressemble à ceci:

public void Method<T>() where T : class 
{} 
public void AnotherMethod() 
{ 
    Assembly assembly = Assembly.GetExecutingAssembly(); 

    var interfaces = from i in assembly.GetTypes() 
    where i.Namespace == "MyNamespace.Interface" // only interfaces stored here 
    select i; 

    foreach(var i in interfaces) 
    { 
     Method<i>(); // Get compile error here! 
    } 




Original post:

Salut!

Je suis en train de boucler à travers toutes les interfaces dans un espace de noms et de les envoyer comme arguments à une méthode générique comme ceci:

public void Method<T>() where T : class 
{} 
public void AnotherMethod() 
{ 
    Assembly assembly = Assembly.GetExecutingAssembly(); 

    var interfaces = from i in assembly.GetTypes() 
    where i.Namespace == "MyNamespace.Interface" // only interfaces stored here 
    select i; 

    foreach(var interface in interfaces) 
    { 
     Method<interface>(); // Get compile error here! 
    } 
} 

L'erreur que je reçois est « Nom du type prévu, mais nom de la variable locale trouvé ". Si je tente

... 
    foreach(var interface in interfaces) 
    { 
     Method<interface.MakeGenericType()>(); // Still get compile error here! 
    } 
} 

Je reçois « Impossible d'appliquer l'opérateur « < » opérandes de type « groupe méthode » et« System.Type » Toute idée sur la façon de contourner ce problème?

Répondre

133

EDIT: Bon, c'est l'heure pour un programme court mais complet. La réponse de base est comme avant:

  • Trouver la méthode générique "ouvert" avec Type.GetMethod
  • Make it générique en utilisant MakeGenericMethod
  • Invoke avec Invoke

Voici quelques exemples de code. Notez que j'ai changé l'expression de la requête en notation par points - cela ne sert à rien d'utiliser une expression de requête quand vous avez simplement une clause where.

using System; 
using System.Linq; 
using System.Reflection; 

namespace Interfaces 
{ 
    interface IFoo {} 
    interface IBar {} 
    interface IBaz {} 
} 

public class Test 
{ 
    public static void CallMe<T>() 
    { 
     Console.WriteLine("typeof(T): {0}", typeof(T)); 
    } 

    static void Main() 
    { 
     MethodInfo method = typeof(Test).GetMethod("CallMe"); 

     var types = typeof(Test).Assembly.GetTypes() 
           .Where(t => t.Namespace == "Interfaces"); 

     foreach (Type type in types) 
     { 
      MethodInfo genericMethod = method.MakeGenericMethod(type); 
      genericMethod.Invoke(null, null); // No target, no arguments 
     } 
    } 
} 

réponse originale

Laissons de côté les problèmes évidents d'appeler une "interface" variable pour commencer.

Vous devez l'appeler par réflexion. Le point de génériques est de mettre plus de vérification de type à compiler temps. Vous ne savez pas quel est le type à la compilation - vous devez donc utiliser des génériques.

Obtenez la méthode générique et appeler MakeGenericMethod dessus, puis l'invoquer.

Est-ce votre type d'interface se fait générique? Je demande parce que vous appelez MakeGenericType là-dessus, mais pas en passant des arguments de type ... Vous essayez d'appeler

Method<MyNamespace.Interface<string>>(); // (Or whatever instead of string) 

ou

Method<MyNamespace.Interface>(); 

Si c'est ce dernier, vous avez seulement besoin d'un appelez MakeGenericMethod - pas MakeGenericType.

+0

Je voudrais bouchonner la méthode générique, en fonction du type. Mais si je le fais en utilisant la réflexion, puis que je talonne celui qui est généré, il comprendra qu'il ne bougera pas ce que je veux. Je suppose que c'est impossible? Ou est-ce? Stub la méthode générique pour tous les types dans une liste ... –

+1

@Stephane: Il est difficile de savoir exactement ce que vous essayez de faire. Je vous suggère de poser une nouvelle question avec plus de détails. –

+0

Notez que vous pouvez obtenir « correspondant Ambigu dans la résolution de la méthode » sur 'GetMethod()'. Cela se produit lorsque la méthode que vous essayez d'obtenir présente des surcharges. Vous devez donc spécifier celui que vous voulez en utilisant 'GetMethod (" Name ", new Type [] {arguments})' – cvsguimaraes