2009-02-25 15 views
11

donnéréférencement souhaité méthode générique surcharge

public Class Example 
{ 

public static void Foo< T>(int ID){} 

public static void Foo< T,U>(int ID){} 

} 

Questions:

  1. Est-il exact d'affirmer que cette "méthode générique surchargé"?
  2. Comment une méthode peut-elle être spécifiée dans la création d'un objet MethodInfo?

    Type exampleType = Type.GetType("fullyqualifiednameOfExample, namespaceOfExample"); 
    MethodInfo mi = exampleType.GetMethod("Foo", BindingFlags.Public|BindingFlags.Static, null, new Type[] {typeof(Type), typeof(Type) }, null); 
    

Argument 4 provoque le compilateur beaucoup déplaisir

+0

Il vous manque un type de retour dans vos définitions de méthode. – Ray

+0

en effet, pas plus, merci. –

Répondre

11

Je ne peux pas trouver un moyen d'utiliser GetMethod qui ferait ce que vous voulez. Mais vous pouvez obtenir toutes les méthodes et parcourir la liste jusqu'à ce que vous trouviez la méthode que vous voulez.

N'oubliez pas que vous devez appeler MakeGenericMethod avant de pouvoir réellement l'utiliser.

var allMethods = typeof (Example).GetMethods(BindingFlags.Public | BindingFlags.Static); 
MethodInfo foundMi = allMethods.FirstOrDefault(
    mi => mi.Name == "Foo" && mi.GetGenericArguments().Count() == 2); 
if (foundMi != null) 
{ 
    MethodInfo closedMi = foundMi.MakeGenericMethod(new Type[] {typeof (int), typeof (string)}); 
    Example example= new Example(); 
    closedMi.Invoke(example, new object[] { 5 }); 
} 
1

Voici un Linq one-liner pour ce que vous avez besoin:

MethodInfo mi = exampleType.GetMethods().First(m=>m.GetGenericArguments().Length == 2); 
+0

C'est exactement ce que j'ai, à quoi ça sert de le repositionner? – Ray

+0

alors que Ray a identifié la bonne stratégie de sussing sur la bonne méthode, merci pour le LINQ one-linner –

+0

Ray: Je suis vraiment vraiment désolé à ce sujet. J'écrivais et je testais dans VS en même temps que toi, seulement, j'ai appuyé sur le bouton soumettre après toi. J'ai édité la réponse pour la rendre moins évidente. Je vous ai plagié. – Coincoin

3

Voici les réponses à vos questions ainsi qu'un exemple:

  1. Oui, bien qu'il y ait deux choses à savoir ici avec les méthodes génériques, l'inférence de type et la résolution de la méthode de surcharge. L'inférence de type se produit au moment de la compilation avant que le compilateur ne tente de résoudre les signatures de méthode surchargées. Le compilateur applique une logique d'inférence de type à toutes les méthodes génériques partageant le même nom. Dans l'étape de résolution de surcharge, le compilateur inclut uniquement les méthodes génériques sur lesquelles l'inférence de type a réussi. More here...

  2. S'il vous plaît voir l'exemple complet Console code de programme d'application ci-dessous qui montre comment plusieurs variantes de la méthode Foo peuvent être spécifiées dans la création d'un objet MethodInfo puis appelé à l'aide d'une méthode d'extension:

Programme .cs

class Program 
{ 
    static void Main(string[] args) 
    { 
     MethodInfo foo1 = typeof(Example).GetGenericMethod("Foo", 
      new[] { typeof(string) }, 
      new[] { typeof(int) }, 
      typeof(void)); 

     MethodInfo foo2 = typeof(Example).GetGenericMethod("Foo", 
      new[] { typeof(string), typeof(int) }, 
      new[] { typeof(int) }, 
      typeof(void)); 

     MethodInfo foo3 = typeof(Example).GetGenericMethod("Foo", 
      new[] { typeof(string) }, 
      new[] { typeof(string) }, 
      typeof(void)); 

     MethodInfo foo4 = typeof(Example).GetGenericMethod("Foo", 
      new[] { typeof(string), typeof(int) }, 
      new[] { typeof(int), typeof(string) }, 
      typeof(string)); 

     Console.WriteLine(foo1.Invoke(null, new object[] { 1 })); 
     Console.WriteLine(foo2.Invoke(null, new object[] { 1 })); 
     Console.WriteLine(foo3.Invoke(null, new object[] { "s" })); 
     Console.WriteLine(foo4.Invoke(null, new object[] { 1, "s" })); 
    } 
} 

Example.cs:

public class Example 
{ 
    public static void Foo<T>(int ID) { } 
    public static void Foo<T, U>(int ID) { } 
    public static void Foo<T>(string ID) { } 
    public static string Foo<T, U>(int intID, string ID) { return ID; } 
} 

Extensions.cs:

public static class Extensions 
{ 
    public static MethodInfo GetGenericMethod(this Type t, string name, Type[] genericArgTypes, Type[] argTypes, Type returnType) 
    { 
     MethodInfo foo1 = (from m in t.GetMethods(BindingFlags.Public | BindingFlags.Static) 
          where m.Name == name && 
          m.GetGenericArguments().Length == genericArgTypes.Length && 
          m.GetParameters().Select(pi => pi.ParameterType).SequenceEqual(argTypes) && 
          m.ReturnType == returnType 
          select m).Single().MakeGenericMethod(genericArgTypes); 

     return foo1; 
    } 
} 
+0

un poste remarquable, merci de mettre sur la clinique –

0

Je fais une petite modification de votre requête lambda.

Lorsque le type de paramètre si vous générique doit faire ce genre:

ajouter pi.ParameterType.GetGenericTypeDefinition()

et

(m.ReturnType.IsGenericType ? m.ReturnType.GetGenericTypeDefinition() : m.ReturnType) == returnType) 

De cette façon, la méthode de travail très fin

MethodInfo foo1 = (from m in t.GetMethods(BindingFlags.Public | BindingFlags.Static) 
         where m.Name == name 
         && m.GetGenericArguments().Length == genericArgTypes.Length 
         && m.GetParameters().Select(pi => pi.ParameterType.IsGenericType ? pi.ParameterType.GetGenericTypeDefinition() : pi.ParameterType).SequenceEqual(argTypes) && 
         (returnType==null || (m.ReturnType.IsGenericType ? m.ReturnType.GetGenericTypeDefinition() : m.ReturnType) == returnType) 
         select m).FirstOrDefault(); 
     if (foo1 != null) 
     { 
     return foo1.MakeGenericMethod(genericArgTypes); 
     } 
     return null; 

Exemple:

Avec la modification de la méthode que je peux appeler cette méthode l'extension

public static IQueryable<T> FilterCulture<T>(this Table<T> t, IDatabaseFilter filter) 

Avec mon nouvel assistant comme celui-ci

var QueryableExpression = MethodInfoHelper.GetGenericMethod(typeof(LinqFilterExtension), "FilterCulture", new Type[] { rowType }, new Type[] { typeof(Table<>), typeof(IDatabaseFilter) }, typeof(IQueryable<>)); 

La signature de mon aide est

public static MethodInfo GetGenericMethod(Type t, string name, Type[] genericArgTypes, Type[] argTypes, Type returnType) 
1

mieux :

Exemple de tentative pour obtenir la surcharge correcte de System.Linq.Enumerable.Select

private static MethodInfo GetMethod<T>(Expression<Func<T>> expression) 
    { 
     return ((MethodCallExpression)expression.Body).Method; 
    } 

    public static void CallSelect() 
    { 
     MethodInfo definition = GetMethod(() => Enumerable.Select(null, (Func<object, object>)null)).GetGenericMethodDefinition(); 
     definition.MakeGenericMethod(typeof(int), typeof(int)).Invoke(null, new object[] { new List<int>(), ((Func<int, int>)(x => x)) }); 
    } 
Questions connexes