使用Expression <Func >以与Func 相同的方式编写调用

考虑一个可以用作多个其他类的成员的类:

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;} } 

我想定义一个方法,为与Customer关联的对象生成检查器。 如果我想要一个内存检查器,我这样做:

 static Func Check(Func conv, string first, string last) { return obj => conv(obj).FirstName == first && conv(obj).LastName == last; } 

我可以使用我的检查器进行内存序列,如下所示:

 var matchingOrders = orders .Where(Check(x => x.Customer, "Foo", "Bar")) .ToList(); var matchingProfiles = profiles .Where(Check(x => x.Customer, "Foo", "Bar")) .ToList(); 

现在我想用Expression<Func>做同样的事情:

 static Expression<Func> Check(Expression<Func> conv, string first, string last) 

不幸的是,同样的技巧不起作用:

 return obj => conv(obj).FirstName == first && conv(obj).LastName == last; 

并像这样使用它:

 var matchingOrders = dbContext.Orders .Where(Check(x => x.Customer, "Foo", "Bar")) .ToList(); var matchingProfiles = dbContext.Profiles .Where(Check(x => x.Customer, "Foo", "Bar")) .ToList(); 

这会触发错误:

CS0119:表达式表示variable', where a期望方法组’

我可以用与撰写代理相同的方式编写表达式吗?

不幸的是,C#目前没有提供一种从Expression>对象组成表达式的方法。 你必须使用表达式树,这是相当长的:

 static Expression> CheckExpr(Expression> conv, string first, string last) { var arg = Expression.Parameter(typeof(T)); var get = Expression.Invoke(conv, arg); return Expression.Lambda>( Expression.MakeBinary( ExpressionType.AndAlso , Expression.MakeBinary( ExpressionType.Equal , Expression.Property(get, nameof(Customer.FirstName)) , Expression.Constant(first) ) , Expression.MakeBinary( ExpressionType.Equal , Expression.Property(get, nameof(Customer.LastName)) , Expression.Constant(last) ) ) , arg ); }