2009-10-26 5 views
6

Ho questo piccolo problema, che non riesco a capire quali argomenti passare a Type.GetMethod per recuperare il MethodInfo di un metodo generico su un tipo non generico. Specificamente, ho questa definizione tipo:Come ottenere MethodInfo di un metodo generico su un tipo .NET non generico?

public static class A 
{ 
    public static B F<T>(bool dummy) 
    { 
    } 
    public static B F<T>(IEnumerable<T> arg) 
    { 
    ... 
    } 
} 

Ho provato diversi prende a Type.GetMethod, ma nessuno restituirebbe MethodInfo del metodo F.

Sono consapevole del fatto che posso richiamare Type.GetMethods o anche Type.FindMember, ma sono interessato a Type.GetMethod.

Qualche idea?

Grazie.

EDIT

In realtà, il mio codice è un po 'più complessa. Il metodo generico è sovraccarico, quindi non posso usare Type.GetMethod con solo il nome della funzione. Ho provato queste varianti:

typeof(A).GetMethod("F", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null) 
typeof(A).GetMethod("F`1", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null) 
typeof(A).GetMethod("F[T]", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null) 
typeof(A).GetMethod("F[[T]]", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null) 
+0

Si prega di inviare il codice che hai provato. –

+0

Modificata la mia domanda. Grazie. – mark

+0

@ Marco Ho cambiato la mia risposta. –

risposta

6

Il problema è che il parametro IEnumerable<> che si sta passando a GetMethod non è specializzato. È davvero un IEnumerable<T>, dove T è specificato dal metodo che si sta tentando di recuperare. Ma non possiamo ottenere tramite MethodInfo.GetGenericArguments() poiché non abbiamo un riferimento al metodo, stiamo ancora cercando di recuperarlo.

Sfortunatamente, questo è il punto in cui la reflection API non è sufficiente. Non esiste un sovraccarico di Type.GetMethod() che consente di distinguere tra i metodi in overload, in cui uno è un metodo generico.

Quindi, con ciò detto, sei bloccato usando Type.GetMethods() e filtrando i risultati con un predicato di tua scelta. Per ottenere il metodo che ti interessa, puoi fare quanto segue.

void getMethod() 
{ 
    typeof(A).GetMethods().Where(m => 
     m.IsGenericMethod && 
     m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() 
      == typeof(IEnumerable<>)); 
} 

N.B. Non ho verificato che sia richiesta la chiamata GetGenericTypeDefinition(); potresti essere in grado di ometterlo. L'idea è che stai trasformando un tipo A<T> in A<>, ma il runtime potrebbe già darlo a te in quel modulo.

5

(Aggiornamento in risposta alla domanda chiarimenti):

Non v'è alcun modo per ottenere un handle per il metodo utilizzando GetMethod (es. Una linea), in quanto la i dati generici per definire il metodo non sono disponibili finché non abbiamo il metodo da ispezionare.

MethodInfo[] methods = typeof(A).GetMethods(BindingFlags.Static | BindingFlags.Public); 
MethodInfo genericMethod = methods.Where(m=>m.IsGenericMethod).First(m=>m.ContainsGenericParameters); 
genericMethod = genericMethod.GetGenericMethodDefinition(); 
  1. Ricevi metodi
  2. Trovare il metodo che ha dei parametri generici (ammesso che abbiate un solo - se si aggiunge più di uno, questo deve essere un po 'più robusto)
  3. Prendi il generic methodinfo
+1

Grazie, ma ho leggermente trasandato nella domanda. L'ho cambiato per essere più preciso. – mark

+0

Grazie, ma come ho detto nella mia domanda, so come farlo con GetMethods o FindMember. Sono specificamente interessato a GetMethod, perché dovrebbe fare anche il lavoro, ma non lo fa e questo mi infastidisce. – mark

+0

@ Mark non c'è modo di farlo, perché i dati generici per definire il metodo non sono disponibili finché non abbiamo il metodo da ispezionare. –