Domanda

dato

public Class Example
{

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

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

}

Domande:

  1. È corretto chiamare questo un "overload del metodo generico"?
  2. Come può il metodo specificato nella creazione di un MethodInfo oggetto?

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

argomento 4 fa sì che il compilatore molto dispiacere

È stato utile?

Soluzione

Non riesco a trovare un modo di usare GetMethod che vorresti fare quello che vuoi.Ma è possibile ottenere tutti i metodi e scorrere l'elenco fino a trovare il metodo che si desidera.

Ricordate che è necessario chiamare MakeGenericMethod prima che si può effettivamente utilizzare.

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 });
}

Altri suggerimenti

Qui ci sono le risposte alle tue domande con un esempio:

  1. Sì, anche se ci sono due cose di essere a conoscenza di qui con metodi generici, tipo di inferenza e di sovraccarico metodo di risoluzione.Tipo di inferenza si verifica al momento della compilazione prima che il compilatore cerca di risolvere metodo di overload firme.Il compilatore si applica il tipo di inferenza logica per tutti i metodi generici che condividono lo stesso nome.Nella risoluzione dell'overload passo, il compilatore include solo i metodi generici su che tipo di inferenza riuscito. Di più qui...

  2. Vedere l'esempio completo programma di Applicazione Console di codice riportato di seguito, che mostra come le diverse varianti del metodo Foo può essere specificato nella creazione di un MethodInfo oggetto e poi richiamato utilizzando un metodo di Estensione:

Programma.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" }));
    }
}

Esempio.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; }
}

Le estensioni.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;
    }
}

Meglio:

Esempio di tentativo di ottenere il corretto sovraccarico di 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)) });
    }

Qui è un Linq one-liner per quello che ti serve:

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

Faccio una piccola modifica della lambda query.

Quando il parametro di tipo generico si deve fare così :

Aggiungo pi.ParameterType.GetGenericTypeDefinition()

e

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

In questo modo il metodo di lavoro molto fine

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;

Esempio :

Con la modifica del metodo posso chiamare questo metodo di estensione

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

Con il mio nuovo Aiutante come questo

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

La firma del mio aiuto è

   public static MethodInfo GetGenericMethod(Type t, string name, Type[] genericArgTypes, Type[] argTypes, Type returnType)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top