将 lambda 作为参数分配给通过反射调用的泛型方法

Assigning a lambda as a parameter to a generic method called through reflection

考虑如下通用方法:

class SomeClass
{
    public static void SomeMethod<T>(Func<T>);
}

我想使用反射来调用这个方法。这是我能做到的程度:

_SomeMethod = typeof(SomeClass).GetMethod("SomeMethod",
    BindingFlags.Public | BindingFlags.Static);
Type type = typeof(SomeType); //Actually SomeType is extracted using reflection and it's not fixed
MethodInfo toBeCalled = _SomeMethod.MakeGenericMethod(type);
object obj = Activator.CreateInstance(type);
toBeCalled.Invoke(null, () => obj);

但是编译报错:

Error CS1660: Cannot convert `lambda expression' to non-delegate type `object' (CS1660)

哪个是绝对可以接受的,但有什么解决办法?

请记住,使用 lambda 创建的 closure 是我需要的东西,所以不要删除它。

[更新]

澄清情况,使之有道理;使用 lambda 创建的仿函数是 SomeMethod 用来创建 class SomeType 实例的实例化器。但我不想在仿函数中实际创建对象,而是 return 从之前的实例化对象集合中创建它。最简单的方法是将 obj 放在由 lambda 编辑的闭包 return 中,你不觉得吗?

简化为最简单的形式,我们有:

void Main()
{
    MethodInfoInvoke(()=> {} );
}

void MethodInfoInvoke(object func)
{
}

失败并出现同样的错误。

现在,如果我们在委托中传递 lambda,似乎更快乐:

void Main()
{
    Object obj = new Object();
    Func<object> action = ()=> obj; ;
    MethodInfoInvoke(action);      // accepted!
}

我认为您希望通过采用 Func<T> 且 "func" 始终是身份的通用方法传递已知对象。多一个包装器可能会有所帮助:

public void SomeMethodInvokerRuntime(Type typeofSomeClass, object obj)
{
    var _SomeMethod = this.GetType().GetMethod("SomeMethodInvoker", 
        BindingFlags.Public | BindingFlags.Static);
    MethodInfo toBeCalled = _SomeMethod.MakeGenericMethod(obj.GetType());
    toBeCalled.Invoke(null, new[]{typeofSomeClass, obj});
}

public static void SomeMethodInvoker<T>(Type typeofSomeClass, T obj)
{
    var _SomeMethod = typeofSomeClass.GetMethod("SomeMethod",
          BindingFlags.Public | BindingFlags.Static);
    MethodInfo toBeCalled = _SomeMethod.MakeGenericMethod(typeof(T));
    Func<T> that = () => obj; // Main part - strongly typed delegate
    toBeCalled.Invoke(null, new[]{that});
}

示例用法:

static class Test
{
    public static void SomeMethod<T>(Func<T> f)
    {
        Console.WriteLine((T)(f()));
    }
}

SomeMethodInvoker(typeof(Test), 3);
object obj = "test";

SomeMethodInvokerRuntime(typeof(Test), obj);

或者,您可以构建表达式并编译成函数,如 所示。

听起来您并不真的需要此处的 lambda 表达式。您可以使用表达式树非常轻松地构建一个 return 常量值的函数:

var expression = Expression.Constant(obj, type);
var delegateType = typeof(Func<>).MakeGenericType(type);
var func = Expression.Lambda(delegateType, expression).Compile();
toBeCalled.Invoke(null, func);