sintaxis sentencias query for c# linq generics reflection

sentencias - linq notation c#



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

Esta pregunta ya tiene una respuesta aquí:

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<Interface1>(); Method<Interface2>(); Method<Interface3>(); ...

Bueno ... pensé que tal vez podría convertirlo en un ciclo utilizando el reflejo. 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<T>() 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<i>(); // 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<T>() 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<interface>(); // Get compile error here! } }

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

... foreach(var interface in interfaces) { Method<interface.MakeGenericType()>(); // 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 programa 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<T>() { 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 objetivo de los genéricos es poner más control de tipos en tiempo de compilación . No sabe cuál es el tipo en tiempo de compilación, por lo tanto, debe usar genéricos.

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<MyNamespace.Interface<string>>(); // (Or whatever instead of string)

o

Method<MyNamespace.Interface>();

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