有兩種方法產生的表達式。
使用編譯器來做到這一點。
Expression<Func<Person, bool>> = p => p.LastName.Contains("A");
限制:可以產生這樣的唯一表達式是LambdaExpression
實例。另外,提取表達的部分並與其他部分結合是相當複雜的。
使用靜態方法System.Linq.Expressions.Expression
。
爲了生成動態表達式,可以任一不同的編譯器生成的表達式之間選擇:或者
// using Record and Records as a placeholder for the actual record type and DbSet property
Expression<Func<Record,bool>> expr;
if (firstParam == "realtor") {
if (secondParam == "clown") {
expr = x => x.A == "realtor" || x.fool == "clown";
} else {
expr = x => x.A == "realtor";
}
} else {
if (secondParam == "clown") {
expr = x => x.fool="clown";
} else {
expr = x => false;
}
}
var ctx = new MyDbContext();
var qry = ctx.Records.Where(expr).Select(x => new {x.A, x.fool});
,可以使用靜態方法動態創建的表達:
(將using System.Linq.Expressions;
和using static System.Linq.Expressions.Expression;
添加到文件頂部。)
Expression expr;
var parameter = Parameter(typeof(Record));
if (firstParam == "realtor") {
expr = Equals(
MakeMemberAccess(parameter, typeof(Record).GetProperty("A")),
Constant("realtor")
);
}
if (secondParam == "clown") {
var exprClown = Equals(
MakeMemberAccess(parameter, typeof(Record).GetProperty("fool")),
Constant("clown")
);
if (expr == null) {
expr = exprClown;
} else {
expr = Or(expr, exprClown);
}
}
var lambda = Lambda<Func<Record,bool>>(expr, new [] {parameter});
var ctx = new MyDbContext();
var qry = ctx.Records.Where(lambda).Select(x => new {x.A, x.fool});
給定一個帶有類型在編譯時未知的查詢,因此任何變量引用它必須是IQueryable
而已,而不是IQueryable<T>
:
IQueryable qry = ctx.GetQuery(); //dynamically built query here
var parameter = Parameter(qry.ElementType);
if (firstParam == "realtor") {
expr = Equals(
MakeMemberAccess(parameter, qry.ElementType.GetProperty("A")),
Constant("realtor")
);
}
if (secondParam == "clown") {
var exprClown = Equals(
MakeMemberAccess(parameter, qry.ElementType.GetProperty("fool")),
Constant("clown")
);
if (expr == null) {
expr = exprClown;
} else {
expr = Or(expr, exprClown);
}
}
var lambda = Lambda(expr, new [] {parameter});
//Since we don't have access to the TSource type to be used by the Where method, we have
//to invoke Where using reflection.
//There are two overloads of Queryable.Where; we need the one where the generic argument
//is Expression<Func<TSource,bool>>, not Expression<Func<TSource,int,bool>>
var miWhere = typeof(Queryable).GetMethods().Single(mi => {
mi.Name == "Where" &&
mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Length == 2
});
qry = miWhere.Invoke(null, new [] {qry, lambda});
您在使用PredicateBuilder麻煩?或者您不能將其用於其他原因? –
我不能帶第三方軟件:-( – frododot
Updated [my answer](http://stackoverflow.com/a/40459470/111794)。 –