以下内容有效,但我的 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)
EditorFor 然后根据元数据在内部将调用委托给特定方法,例如:
public DecimalTextBox DecimalTextBoxFor(Expression<Func<TModel, decimal?>> expression)
DecimalTextBox 有一个十进制类型的 Value 属性?,所以我想设置它:
decimalTextBox.Value(expression.Compile()(ViewData.Model));
从 EditorFor 到 DecimalTextboxFor 的调用无法编译,因为类型不匹配,这就是我需要转换的原因。
上面的代码进行了转换,但是由于 Expression.Body.NodeType 发生了更改,
ModelMetadata.FromLambdaExpression 不起作用,因为表达式类型必须是 ArrayIndex、Call、MemberAccess 或 Parameter。不接受转换。
我的解决方法是将 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>>;
}
但是转换不同的值类型(例如单精度到双精度)当然不起作用。
我希望转换表达式本身......
The following is working, but my Body.NodeType changes to Convert, instead of MemberAccess which is a problem when getting 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;
}
In the context of a ASP.NET MVC 2.0, I have my own EditorFor:
public MvcHtmlString EditorFor<TProperty>(Expression<Func<TModel, TProperty>> expression)
The EditorFor then delegates the call internally, based on metadata, to specific methods, ex:
public DecimalTextBox DecimalTextBoxFor(Expression<Func<TModel, decimal?>> expression)
The DecimalTextBox has a Value property of type decimal?, so I want to set it:
decimalTextBox.Value(expression.Compile()(ViewData.Model));
Call form the EditorFor to the DecimalTextboxFor doesn't compile bacause the types don't match, and that's why I need the conversion.
Above code, does the conversion, but because the Expression.Body.NodeType is changed, the
ModelMetadata.FromLambdaExpression doesn't work, because the expression type needs to be an ArrayIndex, Call, MemberAccess or Parameter. Convert is not accepted.
My workaround is changing the DecimalTextBoxFor into:
public DecimalTextBox DecimalTextBoxFor(Expression<Func<TModel, TProperty>> expression)
and convert the value inside there:
decimalTextBox.Value((decimal?) Convert.ChangeType(expression.Compile()(ViewData.Model), typeof(decimal?)));
An other conversion that does partially work is:
private Expression<Func<TModel, TNewProperty>> ConvertExpression<TProperty, TNewProperty>(Expression<Func<TModel, TProperty>> expression)
{
Expression<Func<TModel, TNewProperty>> convertedExpression = expression as Expression<Func<TModel, TNewProperty>>;
}
But converting different value types (ex. single to double) doesn't work of course.
I was hoping to convert the Expression itself...
发布评论
评论(1)
不幸的是,如果不更改
Body
的NodeType
,这是不可能的。Convert
表达式是一种单独的表达式类型,代表实际操作。为了实现您想要实现的目标,该操作必须是“第一个”操作,即表达式树中的最顶层节点。如果您解释为什么您认为需要 NodeType 保持不变,我也许可以提供解决方法。从语义上讲,这没有意义:旧表达式的
Body
表示特定操作,而新的Body
表示不同操作(即,原始操作后跟Convert
)。您不能期望它代表旧操作但返回新操作的结果。Unfortunately, this is not possible without changing the
NodeType
of theBody
. TheConvert
expression is a separate expression type and represents an actual operation. In order to achieve what you are trying to achieve, that operation has to be the “first” operation, i.e. the topmost node in the expression tree.I might be able to provide a workaround if you explain why you think you need the
NodeType
to remain the same. Semantically this doesn’t make sense: TheBody
of the old expression represents a specific operation, and your newBody
represents a different operation (namely, the original operation followed byConvert
). You can’t expect it to represent the old operation and yet return the result of the new operation.