Llamando al método genérico con un argumento tipo conocido solo en tiempo de ejecución

Editar:

Por supuesto, mi código real no se ve exactamente así. Traté de escribir semi-pseudocódigo para que fuera más claro de lo que quería hacer.

Parece que simplemente arruinó las cosas en su lugar.

Entonces, lo que realmente me gustaría hacer es esto:

Method(); Method(); Method(); ... 

Bueno … pensé que tal vez podría convertirlo en un ciclo utilizando el reflection. Entonces la pregunta es: ¿Cómo lo hago? Tengo un conocimiento muy superficial de la reflexión. Entonces, los ejemplos de código serían geniales.

El escenario se ve así:

 public void Method() where T : class {} public void AnotherMethod() { Assembly assembly = Assembly.GetExecutingAssembly(); var interfaces = from i in assembly.GetTypes() where i.Namespace == "MyNamespace.Interface" // only interfaces stored here select i; foreach(var i in interfaces) { Method(); // Get compile error here! } 


Publicación original:

¡Hola!

Estoy intentando recorrer todas las interfaces en un espacio de nombres y enviarlas como argumentos a un método genérico como este:

 public void Method() where T : class {} public void AnotherMethod() { Assembly assembly = Assembly.GetExecutingAssembly(); var interfaces = from i in assembly.GetTypes() where i.Namespace == "MyNamespace.Interface" // only interfaces stored here select i; foreach(var interface in interfaces) { Method(); // Get compile error here! } } 

El error que recibo es “Nombre del tipo esperado, pero se encontró el nombre de la variable local”. Si bash

 ... foreach(var interface in interfaces) { Method(); // Still get compile error here! } } 

Me aparece “No se puede aplicar el operador ‘<' a los operandos del tipo 'grupo de métodos' y 'Tipo de sistema'". ¿Alguna idea sobre cómo solucionar este problema?

EDITAR: Bien, es hora de un progtwig corto pero completo. La respuesta básica es como antes:

  • Encuentre el método genérico “abierto” con Type.GetMethod
  • Hazlo genérico usando MakeGenericMethod
  • Invocarlo con Invoke

Aquí hay un código de muestra. Tenga en cuenta que cambié la expresión de consulta a notación de puntos: no tiene sentido utilizar una expresión de consulta cuando básicamente acaba de obtener una cláusula where.

 using System; using System.Linq; using System.Reflection; namespace Interfaces { interface IFoo {} interface IBar {} interface IBaz {} } public class Test { public static void CallMe() { Console.WriteLine("typeof(T): {0}", typeof(T)); } static void Main() { MethodInfo method = typeof(Test).GetMethod("CallMe"); var types = typeof(Test).Assembly.GetTypes() .Where(t => t.Namespace == "Interfaces"); foreach (Type type in types) { MethodInfo genericMethod = method.MakeGenericMethod(type); genericMethod.Invoke(null, null); // No target, no arguments } } } 

Respuesta original

Dejemos de lado los problemas obvios de llamar a una “interfaz” variable para empezar.

Tienes que llamarlo por reflexión. El objective de los generics es poner más control de tipos en tiempo de comstackción . No sabe cuál es el tipo en tiempo de comstackción, por lo tanto, debe usar generics.

Obtenga el método genérico y llame a MakeGenericMethod sobre él, luego inícielo.

¿Es tu tipo de interfaz en realidad genérico? Lo pregunto porque está llamando a MakeGenericType, pero no pasa ningún tipo de argumento … ¿Está tratando de llamar?

 Method>(); // (Or whatever instead of string) 

o

 Method(); 

Si es el último, solo necesita una llamada a MakeGenericMethod – no MakeGenericType.