【问题标题】:Removing an unneeded boxing convert from a c# expression从 c# 表达式中删除不需要的装箱转换
【发布时间】: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 基元或枚举类型。”

【问题讨论】:

    标签: c# lambda expression boxing unboxing


    【解决方案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&lt;Func&lt;T,U&gt;&gt; 而不是普通的 LambdaExpression 并在方法本身内部执行强制转换,但在这种情况下,您将无法利用 type-方法调用的推理。

    【讨论】:

    • 这正是我想要的,而且效果很好,谢谢!
    • 谢谢,这真的救了我的命
    猜你喜欢
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 2014-10-22
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    相关资源
    最近更新 更多