Consider a class that can be used as a member of multiple other classes:
class Customer {
public string FirstName {get;set;}
public string LastName {get;set;}
}
// Both "Order" and "Profile" have a "Customer" property
class Order {
public Customer Customer {get;set;}
}
class Profile {
public Customer Customer {get;set;}
}
I want to define a method that makes a checker for an object associated with a Customer
. If I want an in-memory checker, I do it like this:
static Func<T,bool> Check<T>(Func<T,Customer> conv, string first, string last) {
return obj => conv(obj).FirstName == first && conv(obj).LastName == last;
}
I can use my checker for in-memory sequences as follows:
var matchingOrders = orders
.Where(Check<Order>(x => x.Customer, "Foo", "Bar"))
.ToList();
var matchingProfiles = profiles
.Where(Check<Profile>(x => x.Customer, "Foo", "Bar"))
.ToList();
Now I want to do the same thing with Expression<Func<T,bool>>
:
static Expression<Func<T,bool>> Check<T>(Expression<Func<T,Customer>> conv, string first, string last)
Unfortunately, the same trick does not work:
return obj => conv(obj).FirstName == first && conv(obj).LastName == last;
and use it like this:
var matchingOrders = dbContext.Orders
.Where(Check<Order>(x => x.Customer, "Foo", "Bar"))
.ToList();
var matchingProfiles = dbContext.Profiles
.Where(Check<Profile>(x => x.Customer, "Foo", "Bar"))
.ToList();
This triggers an error:
CS0119: Expression denotes a
variable', where a
method group' was expected
Can I compose expressions the same way that I compose delegates?
Unfortunately, C# does not currently provide a way to compose expressions from
Expression<Func<...>>
objects. You have to use expression trees, which is quite a bit longer: