LinqKit System.InvalidCastException在成员属性上调用方法提供的表达式时

use*_*499 18 c# linq entity-framework expression-trees linqkit

给定一个简单的父/子类结构.我想使用linqkit在父级上应用子lambda表达式.我还希望Lambda表达式由实用程序方法提供.

public class Foo
{
    public Bar Bar { get; set; }
}

public class Bar
{
    public string Value { get; set; }
    public static Expression<Func<Bar, bool>> GetLambdaX()
    {
        return c => c.Value == "A";
    }
}
...

Expression<Func<Foo, bool>> lx = c => Bar.GetLambdaX().Invoke(c.Bar);
Console.WriteLine(lx.Expand());
Run Code Online (Sandbox Code Playgroud)

上面的代码抛出

System.InvalidCastException: Unable to cast object of type 
'System.Linq.Expressions.MethodCallExpression' to type 
'System.Linq.Expressions.LambdaExpression'.
at LinqKit.ExpressionExpander.VisitMethodCall(MethodCallExpression m)
at LinqKit.ExpressionVisitor.Visit(Expression exp)
at LinqKit.ExpressionVisitor.VisitLambda(LambdaExpression lambda)
at LinqKit.ExpressionVisitor.Visit(Expression exp)
at LinqKit.Extensions.Expand<TDelegate>(Expression`1 expr)
Run Code Online (Sandbox Code Playgroud)

Fra*_*aft 29

var lambdaX = Bar.GetLambdaX();

Expression<Func<Foo, bool>> lx = c => lambdaX.Invoke(c.Bar);
Run Code Online (Sandbox Code Playgroud)

这有效.

写作要小心

Expression<Func<Foo, bool>> lx = ...
Run Code Online (Sandbox Code Playgroud)

在赋值之前,编译器处理此行,并在您的情况下创建一个分配给lx的方法调用表达式(即用于调用Bar.GetLambdaX()).

如果你使用var ...那么Bar.GetLambdaX(); 调用并赋值,其值(即lambda表达式)稍后用于lx = ...

  • @Servy有趣的是,5年后它仍然没有修复.关注发布您的版本? (5认同)
  • +1很好的答案!编译器如何处理lambda表达式中的语句的上下文差异可能导致一些非常不直观的编译错误. (2认同)
  • @DoctorJones 这不是编译器错误。这只是 LINQKit 中的一个错误。它不支持这种情况。可以编写它来支持此代码并正常工作(我有我自己的相同工具版本,可以很好地处理此代码),但事实并非如此。 (2认同)