20

Given a simple parent/child class structure. I want to use linqkit to apply a child lambda expression on the parent. I also want the Lambda expression to be provided by a utility method.

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

The above code throws

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)
abatishchev
  • 98,240
  • 88
  • 296
  • 433
user293499
  • 203
  • 2
  • 4

2 Answers2

32
var lambdaX = Bar.GetLambdaX();

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

This works.

Be careful with writing

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

Before assignment the compiler processes this line and in your case creates a Method Call Expression (i.e. for calling Bar.GetLambdaX()) that is assigned to lx.

If you use var ... then Bar.GetLambdaX(); is called and assigned, the value of which (which is the lambda expression) is used later in lx = ...

Doctor Jones
  • 21,196
  • 13
  • 77
  • 99
Frank Michael Kraft
  • 2,302
  • 5
  • 25
  • 30
  • 2
    +1 Good answer! The contextual differences of how the compiler treats statements within lambda expressions can lead to some very unintuitive compilation errors. – Doctor Jones Feb 22 '11 at 12:09
  • 2
    @DoctorJones This isn't a compiler error. This is just a bug in LINQKit. It doesn't support this situation when it should. It could be written to support this code and work correctly (I have my own version of the same tool that handles this code just fine), it just wasn't. – Servy Feb 02 '15 at 21:12
  • I didn't say it was a compiler error (i.e. an error with the compiler), I said it was a compilation error (and error that occurred during compilation). I agree that it'd be nice if LINQKit supported this, I too have my own version of LINQKit that handles more situations than it does out of the box. – Doctor Jones Feb 03 '15 at 14:23
  • 8
    @Servy interestingly, 5 years later it is still not fixed. Care to publish your version? – Andrew Savinykh May 27 '15 at 02:47
2

2021 Update: This bug has been fixed as of version 1.1.22.

An issue was opened for this bug in September of 2020, and it was fixed in version 1.1.22 released on January 16th 2021.

NetherGranite
  • 1,940
  • 1
  • 14
  • 42