从c#表达式中删除不需要的装箱转换

时间:2015-11-17 09:38:10

标签: c# lambda expression boxing unboxing

我目前正在尝试转换

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

但是由于底层类型是一个bool,我应该能够完全划伤转换器,对吧?我熟悉表达式访问者等,但仍然无法弄清楚如何删除转换。

编辑:这个问题的接受答案Generic unboxing of Expression<Func<T, object>> to Expression<Func<T, TResult>>(这可能是重复的)对我不起作用......当表达式被EF翻译时,你可以看到它转换(转换())而不是仅删除第一个转换...,这导致&#34;无法转换类型&#39; System.Boolean&#39;键入&#39; System.Object&#39;。 LINQ to Entities仅支持转换EDM原语或枚举类型。&#34;

1 个答案:

答案 0 :(得分:6)

您应该能够使用以下内容删除任何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并在方法内部执行转换,但在这种情况下,您将无法利用类型推理进行方法调用。