2009-01-12 5 views
5

Ich möchte, dies zu tun:Wie kann ich eine Methode durch Reflektion mit einem Lambda-Ausdruck als Parameter aufrufen?

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)}); 

myList eine generische Liste eines bestimmten Typs ist (unbekannt in der Anwendung), und ich möchte es auf eine Liste von Objekten konvertieren einige Operationen zu tun.

Allerdings versagt diese mit diesem Fehler: „Kann nicht Lambda-Ausdruck konvertieren‚Objekt‘zu geben, weil es nicht eine Art delegieren ist“

Können Sie mir helfen zu finden, was falsch ist? Versuche ich etwas zu tun, was nicht möglich ist?

Gibt es eine andere Möglichkeit, dasselbe zu erreichen?

Antwort

5

Ein Lambda-Ausdruck ist wandelbar entweder auf einem Delegattyp oder einen Ausdruck Baum mit der rechten Signatur - aber Sie müssen angeben, welche Delegattyp es ist.

Ich denke, Ihr Code viel einfacher wäre, wenn Sie dies eine generische Methode gemacht:

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

Dann müssen Sie nur finden, und rufen Sie dass Methode generisch:

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}); 

Vollständiges Beispiel:

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

Ein Lambda bildet eine Methode Gruppe (im Prinzip ist dies eine Methode, die nur durch Namen (und Geltungsbereich) identifiziert wird. Da Methoden mit demselben Namen überladen werden können, besteht eine Methodengruppe aus mehreren verschiedenen Mitgliedern). Dies kann nicht immer implizit in einen Delegaten konvertiert werden, da ein Delegat tatsächlich innerhalb einer Methodengruppe an eine einzelne Methode gebunden ist. Dies spielt eine Rolle beim Überladen.

Leider gilt das Gleiche in Ihrem Fall. Das Mittel ist, um einen expliziten Delegaten zu machen:

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

Die Schwierigkeit besteht darin, dass YourType hier zur Kompilierzeit nicht bekannt ist - daher mein Vorschlag, es in eine generische Methode umzuwandeln. –

+0

Ah verdammt, das habe ich nicht beachtet. –

+0

Ja, ich wollte das gleiche sagen ... Danke trotzdem – juan

Verwandte Themen