The first method:
Public Static classpredicateextensions { Public StaticExpression<func<t,BOOL>> true<t> () {returnf =true; } Public StaticExpression<func<t,BOOL>> false<t> () {returnf =false; } Public StaticExpression<func<t,BOOL>> or<t> ( ThisExpression<func<t,BOOL>>expression1, Expression<func<t,BOOL>>expression2) { varInvokedexpression =Expression.invoke (expression2, expression1. Parameters. Cast<Expression>()); returnExpression.lambda<func<t,BOOL>>(Expression.or (expression1. Body, Invokedexpression), expression1. Parameters); } Public StaticExpression<func<t,BOOL>> and<t> ( ThisExpression<func<t,BOOL>>expression1, Expression<func<t,BOOL>>expression2) { varInvokedexpression =Expression.invoke (expression2, expression1. Parameters. Cast<Expression>()); returnExpression.lambda<func<t,BOOL>>(Expression.and (expression1. Body, Invokedexpression), expression1. Parameters); } }
The second method:
Public Static classPredicatebuilder { Public StaticExpression<func<t,BOOL>> true<t> () {returnf =true; } Public StaticExpression<func<t,BOOL>> false<t> () {returnf =false; } Public StaticExpression<t> compose<t> ( ThisExpression<t> First, expression<t> second, func<expression, Expression, expression>merge) { //build parameter map (from parameters of second to parameters of first) varMap = first. Parameters.select ((f, i) = =New{F, s = second. Parameters[i]}). ToDictionary (p = p.s, p =p.f); //Replace parameters in the second lambda expression with parameters from the first varSecondbody =parameterrebinder.replaceparameters (map, second. Body); //apply composition of lambda expression bodies to parameters from the first expression returnExpression.lambda<t>(merge (first). Body, Secondbody), first. Parameters); } Public StaticExpression<func<t,BOOL>> and<t> ( ThisExpression<func<t,BOOL>> First, Expression<func<t,BOOL>>second) { returnFirst.compose (second, expression.and); } Public StaticExpression<func<t,BOOL>> or<t> ( ThisExpression<func<t,BOOL>> First, Expression<func<t,BOOL>>second) { returnFirst.compose (second, expression.or); } }
Note that, by my practical application, I found the first method Predicateextensions class has a flaw, is only suitable for use in Dbdatacontext, if used in Entitycontext, will be error: LINQ to Entities does not support LINQ The expression node type "Invoke". Using the second method will not have this problem, as to the root cause of the problem I have not found the reason, but also look at the high-finger teaching, thank you!
Dynamically constructing query conditions through the LINQ expression tree