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.