2009-10-26 17 views
6

Tengo este pequeño problema, que no puedo descifrar qué argumentos pasar a Type.GetMethod para recuperar el MethodInfo de un método genérico en un tipo no genérico. Específicamente, tengo esta definición de tipo:¿Cómo obtener MethodInfo de un método genérico en un tipo .NET no genérico?

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

He intentado varias tomas al Type.GetMethod, pero ninguno devolvería la MethodInfo del método F.

Soy consciente de que puedo invocar Type.GetMethods o incluso Type.FindMember, pero estoy interesado en Type.GetMethod.

¿Alguna idea?

Gracias.

EDITAR

En realidad, mi código es un poco más compleja. El método genérico está sobrecargado, por lo que no puedo usar Type.GetMethod con solo el nombre de la función. Probé estas variantes:

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

Por favor, publique el código que ha intentado. –

+0

Ha cambiado mi pregunta. Gracias. – mark

+0

@Mark Cambié mi respuesta. –

Respuesta

6

El problema es que el parámetro IEnumerable<> que está pasando al GetMethod no está especializado. Realmente es IEnumerable<T>, donde T está especificado por el método que está tratando de recuperar. Pero no podemos obtener T a través de MethodInfo.GetGenericArguments() ya que no tenemos una referencia al método, todavía estamos tratando de recuperarlo.

Lamentablemente, aquí es donde la API de reflexión se queda corta. No existe una sobrecarga Type.GetMethod() que le permita distinguir entre métodos sobrecargados, donde uno es un método genérico.

Así que dicho esto, estás atascado usando Type.GetMethods() y filtrando los resultados con un predicado de tu elección. Para obtener el método que le interesa, puede hacer lo siguiente.

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

N.B. No he verificado que se requiera la llamada GetGenericTypeDefinition(); es posible que puedas omitirlo. La idea es que está transformando un tipo A<T> en A<>, pero es posible que el tiempo de ejecución ya se lo haya proporcionado en esa forma.

5

(Actualizado en respuesta a la pregunta aclaraciones):

No hay manera de obtener un identificador para el método que utiliza GetMethod (. Por ejemplo una línea), debido a que la los datos genéricos para definir el método no están disponibles hasta que tengamos el método para inspeccionarlos.

MethodInfo[] methods = typeof(A).GetMethods(BindingFlags.Static | BindingFlags.Public); 
MethodInfo genericMethod = methods.Where(m=>m.IsGenericMethod).First(m=>m.ContainsGenericParameters); 
genericMethod = genericMethod.GetGenericMethodDefinition(); 
  1. Obtener los métodos
  2. encontrar el método que tiene parámetros genéricos (suponiendo que sólo tiene un - si se agrega más de uno, esto tiene que ser un poco más robusto)
  3. Obtener el generic methodinfo
+1

Gracias, pero he sido un poco engañado en la pregunta. Lo he cambiado para ser más preciso. – mark

+0

Gracias, pero como menciono en mi pregunta, sé cómo hacerlo con GetMethods o FindMember. Estoy específicamente interesado en GetMethod, porque también debería hacer el trabajo, pero no funciona y eso me molesta. – mark

+0

@Mark no hay forma de hacerlo, porque los datos genéricos para definir el método no estarán disponibles hasta que tengamos el método para inspeccionar. –

Cuestiones relacionadas