LINQ 表达式可以通过System.Linq.Expressions.Expression 类上公开的静态方法轻松构建。
这是一个满足您需求的示例,假设您要针对命名为 SomeClass 的实体构建表达式
[TestMethod]
public void MyTestMethod()
{
var testData = new List<SomeClass>()
{
new SomeClass() {Id=1, CostFree = false, Closed='N', Visible=false},
new SomeClass() {Id=2, CostFree = true, Closed='N', Visible=false}, // expect only this one matching
};
var items = new Dictionary<string, object>();
items.Add("CostFree", true);
items.Add("Visible", true);
items.Add("Closed", 'Y');
// this one will be the "e" in "e => e.CostFree == true || Visible == true || Closed == 'Y'"
var paramExpression = Expression.Parameter(typeof(SomeClass));
// lets construct the body ("e.CostFree == true || Visible == true || Closed == 'Y'") part step-by-step
// the parts consists of binary "equals" expressions combined via logical "or" expression
var bodyExpression = (Expression)null;
foreach(var kvp in items)
{
// get the named property ("CostFree", ...) reference of paramExpression. this is the left hand side of "equals"
var propertyExpression = Expression.PropertyOrField(paramExpression, kvp.Key);
// get the constant with appropriate value to place on right hand side of "equals"
var constantExpression = Expression.Constant(kvp.Value, kvp.Value.GetType());
// combine them into "equals"
var binaryEqualsExpression = Expression.Equal(propertyExpression, constantExpression);
if (bodyExpression == null)
{
bodyExpression = binaryEqualsExpression;
}
else
{
// combine each "equals" parts with logical "or"
bodyExpression = Expression.OrElse(bodyExpression, binaryEqualsExpression);
}
}
// now construct the whole lambda...
var lambdaExpression = Expression.Lambda<Func<SomeClass, bool>>(bodyExpression, paramExpression);
// ...and make it useable in .Where()
var compiledExpression = lambdaExpression.Compile();
// lets execute in on our test data
var r = testData.Where(compiledExpression);
// only #2 should match
Assert.AreEqual(2, r.Single().Id);
}
更新:
我改变了解决方案:
-
items 值的类型为 object
-
constantExpression 尊重值的类型。
这样字典可以包含其他名称-值对和解决方案
仍然有效。字典内容的规则:键必须匹配SomeClass属性名称和值必须匹配给定属性的类型。