2008-11-28 10 views
107

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

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 ha estropeado las cosas en su lugar.

Por lo tanto, lo que realmente me gustaría hacer es la siguiente:

Method<Interface1>(); 
Method<Interface2>(); 
Method<Interface3>(); 
... 

Bueno ... pensé que tal vez podría convertirlo en un bucle que utiliza la reflexión. Entonces la pregunta es: ¿Cómo lo hago? Tengo muy poco profundo conocimiento de la reflexión. Entonces, los ejemplos de código serían geniales.

El escenario es similar a esto:

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! 
    } 




Original post:

Hola!

Estoy tratando de bucle a través de todas las interfaces en un espacio de nombres y enviarlos como argumentos a un método genérico de esta manera:

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 consigo es "nombre de tipo esperado, pero el nombre de variable local encontrado ". Si intento

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

me sale "No se puede aplicar operador < 'a operandos de tipo 'grupo Método' y 'System.Type'" Cualquier idea sobre cómo solucionar este problema?

Respuesta

133

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

  • encontrar el método "abierto" genérico con Type.GetMethod
  • Que sea genérico utilizando MakeGenericMethod
  • Invóquelo con invocación

He aquí algunos ejemplos de código. 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

Vamos a dejar a un lado los problemas obvios de llamar a una "interfaz" variable para empezar.

Tienes que llamar por reflexión. El objetivo de los genéricos es poner más control de tipos en compilar tiempo. 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 y luego inícielo.

¿Es realmente tu tipo de interfaz genérica? Lo pregunto porque usted está llamando MakeGenericType en él, pero que no pasa en ningún tipo de argumentos ... ¿Estás tratando de llamar

Method<MyNamespace.Interface<string>>(); // (Or whatever instead of string) 

o

Method<MyNamespace.Interface>(); 

Si es esto último, sólo se necesita una llama a MakeGenericMethod - no a MakeGenericType.

+0

Me gustaría resumir el método genérico, según el tipo. Pero si lo hago utilizando la reflexión, y luego corto el generado, entiendo que no será lo que quiero. ¿Adivino que es imposible? ¿O es eso? Codifique el método genérico para todos los tipos en una lista ... –

+1

@Stephane: Es difícil saber exactamente lo que está tratando de hacer. Te sugiero que hagas una nueva pregunta con más detalles. –

+0

Tenga en cuenta que puede obtener "correspondencia ambigua en la resolución del método" en 'GetMethod()'. Esto sucede cuando el método que intentas obtener tiene algunas sobrecargas. Por lo tanto, debe especificar cuál desea utilizando 'GetMethod (" Nombre ", nuevo Tipo [] {argumentos})' – cvsguimaraes

Cuestiones relacionadas