如何通过使用lambda表达式作为参数进行反射来调用方法?

时间:2009-01-12 19:40:06

标签: c# generics reflection lambda

我想这样做:

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是特定类型的通用列表(应用程序未知),我想将其转换为对象列表以执行某些操作。

然而,这失败并出现此错误:“无法将lambda表达式转换为'object'类型,因为它不是委托类型”

你能帮我找到什么问题吗?我想做一些不可能的事情吗?

还有其他方法可以达到同样的目的吗?

2 个答案:

答案 0 :(得分:5)

lambda表达式可以转换为具有正确签名的委托类型或表达式树 - 但是您需要指定它是哪种委托类型。

如果您将此代码作为通用方法,我认为您的代码将 更简单:

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

然后你只需要找到并调用那个方法:

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

完整示例:

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 :(得分:1)

lambda形成方法 group (基本上这只是一个由名称(和范围)标识的方法。由于可以重载具有相同名称的方法,因此方法组包含几个不同的成员)。这不能总是隐式转换为委托,因为委托实际上绑定到方法组中的单个方法。这会导致超载。

不幸的是,同样适用于您的情况。补救措施是明确代表:

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