我有这个静态功能
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>
?
答案 0 :(得分:6)
你似乎正在跳过许多不必要的箍。我不明白你为什么要通过表达式树来做这件事。为什么不呢:
public static class Creator<T>
{
public static void Create()
{
Func<T> mainThing = () => (T)SomeClass.Create(typeof(T));
}
}
???
创建方法调用的表达式树的目的是什么,只是将其重新转换为一个委托,然后调用一个方法调用?为什么不直接拨打SomeClass.Create
?
这里有什么我想念的吗?
回答你的实际问题:
如何在编译之前合并演员表?
使用Expression.Convert()
创建表示转换的表达式树节点。
答案 1 :(得分:2)
我认为您只需要拨打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();
(我没有测试过,但看起来还不错......)