在调用成员属性提供的表达式时,出现LinqKit System.InvalidCastException错误。涉及到IT技术领域。

20

给定一个简单的父/子类结构。我想使用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());

上述代码会抛出异常

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)

我本来想帮忙,但是我无法让你的代码编译通过。lx这一行不起作用。 - Nix
对我来说可以编译,lx行应该在一个util方法中。 - user293499
2个回答

32
var lambdaX = Bar.GetLambdaX();

Expression<Func<Foo, bool>> lx = c => lambdaX.Invoke(c.Bar);

这行代码是有效的。

在编写代码时要小心。

Expression<Func<Foo, bool>> lx = ...

在赋值之前,编译器会处理这一行代码,在你的情况下,它创建了一个方法调用表达式(即用于调用Bar.GetLambdaX()的表达式),并将其分配给lx变量。

如果使用var ...,则会调用Bar.GetLambdaX()并进行赋值,然后稍后会使用该值(即lambda表达式)来赋值lx = ...


2
+1 好答案!编译器处理 lambda 表达式中语句的上下文差异可能会导致一些非常令人费解的编译错误。 - Doctor Jones
2
@DoctorJones 这不是编译器错误。这只是LINQKit中的一个bug,它没有支持应该支持的情况。它可以被编写成支持这段代码并正确地工作(我自己有一个处理这段代码的同样工具的版本),只是它没有被支持。 - Servy
我并没有说这是编译器错误(即编译器出错),我说的是编译错误(在编译过程中发生的错误)。我同意如果LINQKit支持这个功能会很好,我也有自己的版本的LINQKit,可以处理比它默认情况下更多的情况。 - Doctor Jones
8
有趣的是,5年后它仍然没有被修复。你愿意发布你的版本吗? - Andrew Savinykh

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接