Non-static Expression<Func<X>> with access to 'this'

c#, expression-trees, lambda, linq, linq-to-sql

Solution

partial class Item
{
    public static Expression<Func<Item, bool>> IsSpecial = (i => Math.Sqrt(i.Id)%2==0);
}

Suggestion: add the `readonly` keyword.

Then I can use that property in a linq-to-sql query like this:

datacontext.Item.Where(Item.IsSpecial)

Right, because `Where` accepts a parameter of type `Expression<Func<Item, bool>>`, which `Item.IsSpecial` is.

Now for aesthetic reasons, I want to make IsSpecial nonstatic and modify it so I can call it like this:

datacontext.Item.Where(i => i.IsSpecial())

The reason this doesn't work is because `IsSpecial` isn't a function, it's an expression tree. `()` can only be applied to functions. An expression tree describes a function, but isn't one. You can create a real function using `expression.Compile()`:

datacontext.Item.Where(i => (IsSpecial.Compile()) (i))

However, this won't work, because again, `Where` is passed an expression tree, and `IsSpecial.Compile()` isn't actually called. LINQ to SQL tries to convert it to SQL, fails because it doesn't recognise `Expression.Compile`, and throws an exception.

However, if you could replace `(IsSpecial.Compile())` before LINQ to SQL were to see it...

That's where LINQKit comes in:

It provides just that bit of expression tree manipulation to get it working.

datacontext.Item.AsExpandable().Where(i => (IsSpecial.Compile()) (i))

The `.AsExpandable()` creates a wrapper around `datacontext.Item` to pre-filter the expression.

Ideally this would also allow combining of statements, which the above (working) snytax does not allow:

datacontext.Item.Where(i => i.IsSpecial() && i.Id >100)

No problem:

datacontext.Item.AsExpandable().Where(i => (IsSpecial.Compile()) (i) && i.Id > 100)

Problem

I have a database table `Item` and access it with linq-to-sql. I can define a custom Method IsSpecial() for Items which returns true if the square root of Item.id is even: ``` partial class Item { public static Expression<Func<Item, bool>> IsSpecial = (i => Math.Sqrt(i.Id)%2==0); } ``` Then I can use that property in a linq-to-sql query like this: ``` datacontext.Item.Where(Item.IsSpecial) ``` Now for aesthetic reasons, I want to make IsSpecial nonstatic and modify it so I can call it like this: ``` datacontext.Item.Where(i => i.IsSpecial()) ``` Ideally this would also allow combining of statements, which the above (working) snytax does not allow: ``` datacontext.Item.Where(i => i.IsSpecial() && i.Id >100) ``` What is the correct syntax for defining this method? This does not work: ``` partial class Item { public Expression<Func<bool>> IsSpecial = ( () => Math.Sqrt(this.Id)%2==0 ); // 'this' keyword not available in current context } ``` edit: I am beginning to suspect that I am asking for something that the syntax simply does not allow I guess I can live with `datacontext.Item.Where(Item.IsSpecial).Where(i => i>100)`

Original source