转换函数<类型,对象>表达式为Func其中T是一般约束

本文关键字:其中 约束 Func 表达式 类型 函数 对象 转换 | 更新日期: 2023-09-27 18:10:38

我有这个静态函数

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> ?

转换函数<类型,对象>表达式为Func<T>其中T是一般约束

你似乎跳过了很多不必要的环节。我不明白你为什么要用表达式树来做这个。为什么不直接:

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

? ?

创建一个方法调用的表达式树的目的是什么,只是把它变成一个委托,使一个方法调用,然后调用?为什么不直接打电话给SomeClass.Create ?

我在这里错过了什么吗?

回答你的实际问题:

如何在编译前合并强制转换?

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

我认为你只需要调用Expression.Convert,并使用ConstantExpression而不是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();

(我还没有测试,但它看起来不错…)