55 votes

Comment appeler une méthode générique avec un objet Type donné?

Je veux appeler ma méthode générique avec un objet type donné.

 void Foo(Type t)
{
     MyGenericMethod<t>();
}
 

ne fonctionne évidemment pas.

Comment puis-je le faire fonctionner?

56voto

Erik van Brakel Points 7589

L'exemple de code ne fonctionne pas, parce que la méthode générique s'attend à un identificateur de type, pas une instance de la classe Type. Vous aurez à utiliser la réflexion pour le faire:

public class Example {

    public void CallingTest()
    {
        MethodInfo method = typeof (Example).GetMethod("Test");
        MethodInfo genericMethod = method.MakeGenericMethod(typeof (string));
        genericMethod.Invoke(this, null);

    }

    public void Test<T>()
    {
        Console.WriteLine(typeof (T).Name);
    }
}

Ne gardez à l'esprit que ce est très fragile, je préfère suggérer de trouver un autre motif pour appeler votre méthode.

Un autre hacky solution (peut-être que quelqu'un peut faire un peu plus propre) serait d'utiliser une expression de la magie:

public class Example {

    public void CallingTest()
    {
        MethodInfo method = GetMethod<Example>(x => x.Test<object>());
        MethodInfo genericMethod = method.MakeGenericMethod(typeof (string));
        genericMethod.Invoke(this, null);

    }

    public static MethodInfo GetMethod<T>(Expression<Action<T>> expr)
    {
        return ((MethodCallExpression) expr.Body)
            .Method
            .GetGenericMethodDefinition();
    }

    public void Test<T>()
    {
        Console.WriteLine(typeof (T).Name);
    }
}

La Note de passage de l '"objet" de type identifiant comme un argument de type générique dans le lambda. Ne pouvais pas comprendre si rapidement comment obtenir autour de cela. De toute façon, c'est au moment de la compilation en sécurité je pense. Il se sent juste mal en quelque sorte :/

18voto

Jon Skeet Points 692016

Vous devez utiliser la réflexion, malheureusement (pour les raisons Jared mentionné). Par exemple:

MethodInfo method = typeof(Foo).GetMethod("MyGenericMethod");
method = method.MakeGenericMethod(t);
method.Invoke(this, new object[0]);

Évidemment, vous voulez plus de contrôle d'erreur dans la réalité :)


Note de côté: mon MSDN local ne spécifie pas que le paramètre de MakeGenericMethod est un tableau de paramètres, donc, je n'aurais probablement besoin:

method = method.MakeGenericMethod(new Type[] { t });

mais il semble que c' est un tableau de paramètres dans la réalité, et la MSDN en ligne docs d'accord. Impair.

-2voto

JaredPar Points 333733

Cette approche ne fonctionnera pas. La raison en est que Type est un objet dont le type est déterminé lors de l'exécution. Cependant, vous essayez de l'utiliser pour appeler une méthode générique. Un type d'appel de méthode générique est établi au moment de la compilation. Par conséquent, un objet Type ne peut jamais être utilisé pour un paramètre de type sur une méthode générique.

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