123 votes

L'appel de méthode générique avec un argument de type connu seulement au moment de l'exécution

Edit:

Bien sûr que mon code n'est pas exactement comme cela. J'ai essayé d'écrire semi-pseudo-code pour le rendre plus clair de pourquoi je voulais faire.

Ressemble juste gâché les choses à la place.

Donc, ce que je voudrais faire est ceci:

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

Bien ... je pensais que peut-être je pourrais le transformer en une boucle à l'aide de la réflexion. La question est donc: Comment puis-je le faire. J'ai très peu profonde connaissance de la réflexion. Donc, des exemples de code serait génial.

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 faire une boucle par toutes les interfaces dans un espace de noms et de les envoyer, comme les arguments d'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 j'obtiens est "nom du Type prévu, mais nom de variable locale". Si j'essaie

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

J'ai "Impossible d'appliquer l'opérateur '<' pour des opérandes de type "méthode" groupe " et " le Système de.Le "Type" Aucune idée sur comment contourner ce problème?

144voto

Jon Skeet Points 692016

EDIT: Bon, le temps d'une courte mais complète du programme. La réponse basique est comme avant:

  • Trouver la fonction "ouvrir" méthode générique avec le Type.GetMethod
  • Le rendre générique à l'aide de MakeGenericMethod
  • L'invoquer à l'Invoquer

Voici un exemple de code. Notez que j'ai changé l'expression de la requête à la notation de point - il n'y a pas de point à l'aide d'une expression de requête lorsque vous avez fondamentalement juste obtenu 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(new Type[] {type});
            genericMethod.Invoke(null, null); // No target, no arguments
        }
    }
}

Réponse originale à cette question

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

Il faut l'appeler par la réflexion. Le point de génériques est de mettre plus de la vérification de type à la compilation du temps. Vous ne savez pas de quel type est au moment de la compilation, donc vous devez utiliser des génériques.

Obtenir la méthode générique, et appel MakeGenericMethod sur elle, puis l'appeler.

Est votre type d'interface elle-même en fait générique? Je demande parce que vous êtes d'appel MakeGenericType sur elle, mais ne passant pas dans n'importe quel type d'arguments... Êtes-vous essayer de les appeler

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

ou

Method<MyNamespace.Interface>();

Si c'est le deuxième cas, vous avez seulement besoin d'un appel à MakeGenericMethod - pas MakeGenericType.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X