从 c# 表达式中删除不需要的装箱转换
Posted
技术标签:
【中文标题】从 c# 表达式中删除不需要的装箱转换【英文标题】:Removing an unneeded boxing convert from a c# expression 【发布时间】:2016-02-18 14:53:57 【问题描述】:我目前正在尝试转换
Expression<Func<T,object>>
到一个
Expression<Func<T,bool>>
目前手表显示我的表情保持不变
Expression<Func<T,object>> myExpression = model=>Convert(model.IsAnAirplane)
我想把它简化为
Expression<Func<T,bool>> myExpression = model=>model.IsAnAirplane
目前我只成功添加了一个转换,导致:
Expression<Func<T,bool>> myExpression = model=>Convert(Convert(model.IsAnAirplane))
但由于底层类型是布尔型,我应该能够完全从头开始转换,对吧?我对表达式访问者等很熟悉,但仍然不知道如何删除转换。
编辑:这个问题的公认答案Generic unboxing of Expression<Func<T, object>> to Expression<Func<T, TResult>>(可能是重复的)对我不起作用......因为表达式被 EF 翻译,你可以看到它确实 Convert(Convert())而不是仅仅删除第一个转换...,这会导致“无法将类型 'System.Boolean' 转换为类型 'System.Object'。LINQ to Entities 仅支持转换 EDM 基元或枚举类型。”
【问题讨论】:
【参考方案1】:您应该能够使用类似这样的方式剥离任何 Convert
包装器:
Expression<Func<YourModel, object>> boxed = m => m.IsAnAirplane;
var unboxed = (Expression<Func<YourModel, bool>>)StripConvert(boxed);
// ...
public static LambdaExpression StripConvert<T>(Expression<Func<T, object>> source)
Expression result = source.Body;
// use a loop in case there are nested Convert expressions for some crazy reason
while (((result.NodeType == ExpressionType.Convert)
|| (result.NodeType == ExpressionType.ConvertChecked))
&& (result.Type == typeof(object)))
result = ((UnaryExpression)result).Operand;
return Expression.Lambda(result, source.Parameters);
如果您愿意,您可以更改 StripConvert
以返回 Expression<Func<T,U>>
而不是普通的 LambdaExpression
并在方法本身内部执行强制转换,但在这种情况下,您将无法利用 type-方法调用的推理。
【讨论】:
这正是我想要的,而且效果很好,谢谢! 谢谢,这真的救了我的命以上是关于从 c# 表达式中删除不需要的装箱转换的主要内容,如果未能解决你的问题,请参考以下文章