扩展Expression表达式树,实现EF动态条件查询
在我们写一些管理系统后台的时候,经常会出现带多个查询参数的情况。如果按照一般方法就是if里面嵌套if-else 多层,这样代码看起来很乱。
我们通过扩展表达式树就可以实现这些功能。
//主方法 public static void Main(string[] args) { MyWhere<tb_test> where = new MyWhere<tb_test>(); //if (xxxx) where.And(m => m.id >= 2); //if(xxxx) where.And(m => m.name.Contains("test")); //where.Or(m => m.name.Contains("test")); var result = new List<tb_test>(); using (MysqlTestDB db = new MysqlTestDB()) { result = db.tb_tests.Where(where.GetExpression()).ToList(); } foreach (var item in result) { Console.WriteLine("id: "+ item.id + ",name: "+item.name); } }
//MyWhere工具类 public class MyWhere<T> { private Expression<Func<T, bool>> _expressions = e => true; public void And(Expression<Func<T, bool>> exp) { _expressions = _expressions.AndAlso(exp, Expression.AndAlso); } public void Or(Expression<Func<T, bool>> exp) { _expressions = _expressions.AndAlso(exp, Expression.OrElse); } public Expression<Func<T, bool>> GetExpression() { return _expressions; } }
//Expressing扩展类 public static class ExpressionExtensions { public static Expression<Func<T, bool>> And<T>( this Expression<Func<T, bool>> first, Expression<Func<T, bool>> secend) { return first.AndAlso(secend, Expression.AndAlso); } public static Expression<Func<T, bool>> Or<T>( this Expression<Func<T, bool>> first, Expression<Func<T, bool>> secend) { return first.AndAlso(secend, Expression.OrElse); } public static Expression<Func<T, bool>> AndAlso<T>( this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2, Func<Expression,Expression,BinaryExpression> func) { var parameter = Expression.Parameter(typeof(T)); var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0],parameter); var left = leftVisitor.Visit(expr1.Body); var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter); var right = rightVisitor.Visit(expr2.Body); return Expression.Lambda<Func<T, bool>>(func(left, right), parameter); } private class ReplaceExpressionVisitor : ExpressionVisitor { private readonly Expression _oldValue; private readonly Expression _newValue; public ReplaceExpressionVisitor(Expression oldValue, Expression newValue) { _oldValue = oldValue; _newValue = newValue; } public override Expression Visit(Expression node) { if (node == _oldValue) return _newValue; return base.Visit(node); } } }
数据库:
结果截图:
1-当 选择 And 包含 "test" 时
2-当选择 Or 包含 "test" 时