2009-01-12 12 views
5

Quiero hacer esto:¿Cómo invoco un método a través de la reflexión con una expresión lambda como parámetro?

MethodInfo m = myList.GetType().GetMethod("ConvertAll", System.Reflection.BindingFlags.InvokeMethod).MakeGenericMethod(typeof(object)); 
List<object> myConvertedList = (List<object>)m.Invoke(myList, new object[]{ (t => (object)t)}); 

miLista es una lista genérica de un tipo específico (desconocido para la aplicación), y quiero convertirlo en una lista de objetos para hacer algunas operaciones.

Sin embargo, esto produce este error: "No se puede convertir la expresión lambda para escribir 'objeto' porque no es un tipo de delegado"

¿Puede ayudarme a encontrar lo que está mal? ¿Estoy tratando de hacer algo que no es posible?

¿Hay alguna otra manera de lograr lo mismo?

Respuesta

5

Una expresión lambda es convertible ya sea a un tipo de delegado o un árbol de expresión con la firma derecha - pero hay que especificar qué tipo de delegado que es.

Creo que su código sería mucho más simple si usted hizo esto un método genérico:

public static List<object> ConvertToListOfObjects<T>(List<T> list) 
{ 
    return list.ConvertAll<object>(t => t); 
} 

A continuación, sólo tiene que encontrar e invocar que método genéricamente:

MethodInfo method = typeof(Foo).GetMethod("ConvertToListOfObjects", 
    BindingFlags.Static | BindingFlags.Public); 
Type listType = list.GetType().GetGenericArguments()[0]; 
MethodInfo concrete = method.MakeGenericMethod(new [] { listType }); 
List<object> objectList = (List<object>) concrete.Invoke(null, 
                new object[]{list}); 

Ejemplo completo:

using System; 
using System.Reflection; 
using System.Collections.Generic; 

class Test 
{ 
    public static List<object> ConvertToListOfObjects<T>(List<T> list) 
    { 
     return list.ConvertAll<object>(t => t); 
    } 

    static void Main() 
    { 
     object list = new List<int> { 1, 2, 3, 4 }; 

     MethodInfo method = typeof(Test).GetMethod("ConvertToListOfObjects", 
      BindingFlags.Static | BindingFlags.Public); 
     Type listType = list.GetType().GetGenericArguments()[0]; 
     MethodInfo concrete = method.MakeGenericMethod(new [] { listType }); 
     List<object> objectList = (List<object>) concrete.Invoke(null, 
                new object[] {list}); 

     foreach (object o in objectList) 
     { 
      Console.WriteLine(o); 
     } 
    } 
} 
1

Una lambda forma un método grupo (básicamente, este es un método identificado solo por el nombre (y el alcance). Como los métodos con el mismo nombre pueden estar sobrecargados, un grupo de métodos comprende varios miembros diferentes). Esto no siempre se puede convertir implícitamente en un delegado porque un delegado está realmente vinculado a un único método dentro de un grupo de métodos. Esto juega un rol con la sobrecarga.

Lamentablemente, lo mismo aplica en su caso. El remedio es hacer un delegado explícita:

List<object> myConvertedList = (List<object>)m.Invoke(myList, new object[]{ new Func<YourType, object>(t => (object)t)}); 
+1

La dificultad es que YourType no se conoce en tiempo de compilación aquí; de ahí mi sugerencia de convertirlo en un método genérico. –

+0

Ah maldita sea, no le presté atención a eso. –

+0

Sí, estaba a punto de comentar lo mismo ... Gracias de todos modos – juan

Cuestiones relacionadas