1

我有这个静态函数

public static object Create(Type t)
{
    //unimportant
}

我无法控制上述功能,因此无法更改。问题是它不是通用的,所以我必须将返回的对象转换为某种类型。这种类型是由我调用该Create方法的另一个泛型类的约束提供的。

这是我到达的地方:

public static class Creator<T>
{
    public static void Create()
    {
        var m = typeof(SomeClass).GetMethod("Create");
        var p = Expression.Parameter(typeof(Type));
        var e = Expression.Call(m, p);

        //at this stage I want to create delegate for calling the 'Create' method, 
        //then pass typeof(T) as parameter, get returned object, 
        //and finally cast it to 'T'.

        //for eg, I can do it like this:
        var f = Expression.Lambda<Func<Type, object>>(e, p).Compile();
        Func<T> mainThing = () => (T)f(typeof(T));

        //is there a way I can achieve in one step?
    }
}

在我上面的方法中,我不是在编译最终的委托,而是在编译之前的一步。我如何在编译之前合并演员表并Func<T>返回?

4

2 回答 2

6

你似乎跳过了很多不必要的圈子。我不明白您为什么要通过表达式树来执行此操作。为什么不只是:

public static class Creator<T>
{
    public static void Create()
    {
        Func<T> mainThing = () => (T)SomeClass.Create(typeof(T));
    }
}

???

创建一个方法调用的表达式树只是为了将其转换回一个委托,然后再调用一个方法调用的目的是什么?为什么不直接打电话SomeClass.Create呢?

我在这里缺少什么吗?

要回答您的实际问题:

在编译之前如何合并演员表?

用于Expression.Convert()创建表示转换的表达式树节点。

于 2013-04-23T17:12:16.870 回答
2

我认为您只需要调用Expression.Convert,并使用 aConstantExpression而不是 a ParameterExpression

var method = typeof(SomeClass).GetMethod("Create");
var call = Expression.Call(method, Expression.Constant(typeof(T), typeof(Type)));
var conversion = Expression.Convert(call, typeof(T));
var function = Expression.Lambda<Func<T>>(conversion).Compile();

(我还没有测试过,但看起来还可以......)

于 2013-04-23T17:10:28.737 回答