如何将Expression<Func<T, TProperty>>转换为Expression<Func<T, TNewProperty>>?

3
以下代码可以工作,但是我的 Body.NodeType 变成了 Convert,而不是 MemberAccess,这会在获取 ModelMetadata.FromLambdaExpression 时造成问题:
private Expression<Func<TModel, TNewProperty>> ConvertExpression<TProperty, TNewProperty>(Expression<Func<TModel, TProperty>> expression)
{
    Exression converted = Expression.Convert(expression.Body, typeof(TNewProperty));
    var result =  Expression.Lambda<Func<TModel, TNewProperty>>(converted,    expression.Parameters);
    return result;
}

在ASP.NET MVC 2.0的情境下,我有自己的EditorFor:
public MvcHtmlString EditorFor<TProperty>(Expression<Func<TModel, TProperty>> expression)

编辑器For然后根据元数据在内部委派调用到特定的方法,例如:
public DecimalTextBox DecimalTextBoxFor(Expression<Func<TModel, decimal?>> expression)

DecimalTextBox有一个名为Value的属性,类型为decimal?,因此我想设置它:
decimalTextBox.Value(expression.Compile()(ViewData.Model));

从EditorFor调用DecimalTextboxFor时,由于类型不匹配,代码无法编译,因此需要进行转换。
尽管上述代码执行了转换操作,但由于Expression.Body.NodeType已更改,因此ModelMetadata.FromLambdaExpression无法正常工作,因为表达式类型必须是ArrayIndex、Call、MemberAccess或Parameter,而Convert则不被接受。
我的解决方法是将DecimalTextBoxFor更改为:
public DecimalTextBox DecimalTextBoxFor(Expression<Func<TModel, TProperty>> expression)

并将其中的值转换:

decimalTextBox.Value((decimal?) Convert.ChangeType(expression.Compile()(ViewData.Model), typeof(decimal?)));

一个部分有效的转换是:

另一个部分有效的转换是:

private Expression<Func<TModel, TNewProperty>> ConvertExpression<TProperty, TNewProperty>(Expression<Func<TModel, TProperty>> expression)
{
     Expression<Func<TModel, TNewProperty>> convertedExpression = expression as Expression<Func<TModel, TNewProperty>>;
}

但是转换不同的值类型(如从单精度转为双精度)当然是行不通的。

我希望能够转换表达式本身...


我不明白这个问题。你之所以得到一个Convert,是因为你自己造成的。 - leppie
问题在于表达式.Body.NodeType 会发生变化。 有没有一种方法可以在不改变表达式.Body.NodeType 的情况下进行转换? - Linefeed
1个回答

1

很遗憾,如果不改变BodyNodeType,这是不可能实现的。 Convert表达式是一个单独的表达式类型,代表了一个实际的操作。为了实现您想要的效果,该操作必须是“第一个”操作,即表达式树中最顶层的节点。

如果您能解释清楚为什么需要保持NodeType不变,我可能能够提供一种解决方法。从语义上讲,这是没有意义的:旧表达式的Body表示特定的操作,而新的Body表示一个不同的操作(即原始操作后跟Convert)。您不能指望它表示旧操作并返回新操作的结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接