I want to do this:
我想做这个:
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 is a generic list of a specific type (unknown to the application), and I want to convert it to a list of objects to do some operations.
myList是特定类型的通用列表(应用程序未知),我想将其转换为对象列表以执行某些操作。
However this fails with this error: "Cannot convert lambda expression to type 'object' because it is not a delegate type"
但是这会失败,并显示以下错误:“无法将lambda表达式转换为'object'类型,因为它不是委托类型”
Can you help me find what's wrong? Am I trying to do something that's not possible?
你能帮我找到什么问题吗?我想做一些不可能的事吗?
Is there some other way to achieve the same thing?
有没有其他方法来实现同样的事情?
2 个解决方案
#1
A lambda expression is convertible to either a delegate type or an expression tree with the right signature - but you need to specify which delegate type it is.
lambda表达式可以转换为具有正确签名的委托类型或表达式树 - 但您需要指定它是哪种委托类型。
I think your code would be much simpler if you made this a generic method:
我认为如果你把它作为一个通用的方法,你的代码会简单得多:
public static List<object> ConvertToListOfObjects<T>(List<T> list)
{
return list.ConvertAll<object>(t => t);
}
Then you just need to find and invoke that method generically:
然后你只需要通常找到并调用该方法:
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});
Complete example:
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);
}
}
}
#2
A lambda forms a method group (basically this is a method identified by name (and scope) only. Since methods with the same name can be overloaded, a method group comprises several different members). This cannot always implicitly be converted to a delegate because a delegate is actually bound to a single method from within a method group. This plays a role with overloading.
lambda形成一个方法组(基本上这只是一个由名称(和范围)标识的方法。由于可以重载具有相同名称的方法,因此方法组包含几个不同的成员)。这不能总是隐式转换为委托,因为委托实际上绑定到方法组中的单个方法。这对重载起着重要作用。
Unfortunately, the same applies in your case. The remedy is to make an explicit delegate:
不幸的是,同样适用于您的情况。补救措施是制作一个明确的代表:
List<object> myConvertedList = (List<object>)m.Invoke(myList, new object[]{ new Func<YourType, object>(t => (object)t)});
#1
A lambda expression is convertible to either a delegate type or an expression tree with the right signature - but you need to specify which delegate type it is.
lambda表达式可以转换为具有正确签名的委托类型或表达式树 - 但您需要指定它是哪种委托类型。
I think your code would be much simpler if you made this a generic method:
我认为如果你把它作为一个通用的方法,你的代码会简单得多:
public static List<object> ConvertToListOfObjects<T>(List<T> list)
{
return list.ConvertAll<object>(t => t);
}
Then you just need to find and invoke that method generically:
然后你只需要通常找到并调用该方法:
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});
Complete example:
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);
}
}
}
#2
A lambda forms a method group (basically this is a method identified by name (and scope) only. Since methods with the same name can be overloaded, a method group comprises several different members). This cannot always implicitly be converted to a delegate because a delegate is actually bound to a single method from within a method group. This plays a role with overloading.
lambda形成一个方法组(基本上这只是一个由名称(和范围)标识的方法。由于可以重载具有相同名称的方法,因此方法组包含几个不同的成员)。这不能总是隐式转换为委托,因为委托实际上绑定到方法组中的单个方法。这对重载起着重要作用。
Unfortunately, the same applies in your case. The remedy is to make an explicit delegate:
不幸的是,同样适用于您的情况。补救措施是制作一个明确的代表:
List<object> myConvertedList = (List<object>)m.Invoke(myList, new object[]{ new Func<YourType, object>(t => (object)t)});