遍历/修改表达式树 可以使用 ExpressionVisitor 类遍历现有表达式树,以及复制它访问的每个节点。
表达式的遍历 参考:
ExpressionType
Expression
ExpressionVisitor
表达式类型
表达式操作节点类型
ExpressionVisitor类访问方法
UnaryExpression
ExpressionType.ArrayLength ExpressionType.ArrayLength ExpressionType.Convert ExpressionType.ConvertChecked ExpressionType.Decrement ExpressionType.Increment ExpressionType.Negate ExpressionType.NegateChecked ExpressionType.Not ExpressionType.NotEqual ExpressionType.Quote ExpressionType.TypeAs
VisitUnary(UnaryExpression)
BinaryExpression
ExpressionType.Add ExpressionType.AddAssignExpressionType.AddAssignCheckedExpressionType.AddCheckedExpressionType.AndExpressionType.AndAlsoExpressionType.AndAssignExpressionType.ArrayIndexExpressionType.AssignExpressionType.CoalesceExpressionType.DivideExpressionType.DivideAssignExpressionType.EqualExpressionType.GreaterThanExpressionType.GreaterThanOrEqualExpressionType.LessThanExpressionType.LessThanOrEqualExpressionType.ModuloExpressionType.ModuloAssignExpressionType.MultiplyExpressionType.MultiplyAssignExpressionType.NotEqualExpressionType.OrExpressionType.OrElseExpressionType.Subtract
VisitBinary(BinaryExpression)
BlockExpression
ExpressionType.Block
VisitBlock(BlockExpression)
ConditionalExpression
ExpressionType.Conditional
VisitConditional(ConditionalExpression)
ConstantExpression
ExpressionType.Constant
VisitConstant(ConstantExpression)
ParameterExpression
ExpressionType.Parameter
VisitParameter(ParameterExpression)
MemberExpression
ExpressionType.MemberAccess
VisitMember(MemberExpression)
MemberInitExpression
ExpressionType.MemberInit
VisitMemberInit(MemberInitExpression)
MethodCallExpression
ExpressionType.Call
VisitMethodCall(MethodCallExpression)
LambdaExpression
ExpressionType.Lambda
VisitLambda()
NewExpression
ExpressionType.New
VisitNew(NewExpression)
NewArrayExpression
ExpressionType.NewArrayBoundsExpressionType.NewArrayInit
VisitNewArray(NewArrayExpression)
InvocationExpression
ExpressionType.Invoke
VisitInvocation(InvocationExpression)
ListInitExpression
ExpressionType.ListInit
VisitListInit(ListInitExpression)
TypeBinaryExpression
ExpressionType.TypeIs
VisitTypeBinary(TypeBinaryExpression)
扩展IQueryable的Where方法,根据输入的查询条件来构造SQL语句。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 internal class Program { private static void Main (string [] args ) { List<User> myUsers = new List<User>(); var userSql = myUsers.AsQueryable().Where(u => u.Age > 2 ); Console.WriteLine(userSql); List<User> myUsers2 = new List<User>(); var userSql2 = myUsers2.AsQueryable().Where(u => u.Name == "QueryExtension" ); Console.WriteLine(userSql2); Console.ReadKey(); } } public class User { public string Name { get ; set ; } public int Age { get ; set ; } } public static class QueryExtensions { public static string Where <TSource >(this IQueryable<TSource> source, Expression<Func<TSource, bool >> predicate ) { var expression = Expression.Call(null , ((MethodInfo)MethodBase.GetCurrentMethod()) .MakeGenericMethod(new Type[] { typeof (TSource) }), new Expression[] { source.Expression, Expression.Quote(predicate) }); var translator = new QueryTranslator(); return translator.Translate(expression); } } internal class QueryTranslator : ExpressionVisitor { private StringBuilder sb; internal string Translate (Expression expression ) { this .sb = new StringBuilder(); this .Visit(expression); return this .sb.ToString(); } private static Expression StripQuotes (Expression e ) { while (e.NodeType == ExpressionType.Quote) { e = ((UnaryExpression)e).Operand; } return e; } protected override Expression VisitMethodCall (MethodCallExpression m ) { if (m.Method.DeclaringType == typeof (QueryExtensions) && m.Method.Name == "Where" ) { sb.Append("SELECT * FROM (" ); this .Visit(m.Arguments[0 ]); sb.Append(") AS T WHERE " ); LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1 ]); this .Visit(lambda.Body); return m; } throw new NotSupportedException(string .Format("方法{0}不支持" , m.Method.Name)); } protected override Expression VisitUnary (UnaryExpression u ) { switch (u.NodeType) { case ExpressionType.Not: sb.Append(" NOT " ); this .Visit(u.Operand); break ; default : throw new NotSupportedException(string .Format("运算{0}不支持" , u.NodeType)); } return u; } protected override Expression VisitBinary (BinaryExpression b ) { sb.Append("(" ); this .Visit(b.Left); switch (b.NodeType) { case ExpressionType.And: sb.Append(" AND " ); break ; case ExpressionType.Or: sb.Append(" OR" ); break ; case ExpressionType.Equal: sb.Append(" = " ); break ; case ExpressionType.NotEqual: sb.Append(" <> " ); break ; case ExpressionType.LessThan: sb.Append(" < " ); break ; case ExpressionType.LessThanOrEqual: sb.Append(" <= " ); break ; case ExpressionType.GreaterThan: sb.Append(" > " ); break ; case ExpressionType.GreaterThanOrEqual: sb.Append(" >= " ); break ; default : throw new NotSupportedException(string .Format("运算符{0}不支持" , b.NodeType)); } this .Visit(b.Right); sb.Append(")" ); return b; } protected override Expression VisitConstant (ConstantExpression c ) { IQueryable q = c.Value as IQueryable; if (q != null ) { sb.Append("SELECT * FROM " ); sb.Append(q.ElementType.Name); } else if (c.Value == null ) { sb.Append("NULL" ); } else { switch (Type.GetTypeCode(c.Value.GetType())) { case TypeCode.Boolean: sb.Append(((bool )c.Value) ? 1 : 0 ); break ; case TypeCode.String: sb.Append("'" ); sb.Append(c.Value); sb.Append("'" ); break ; case TypeCode.Object: throw new NotSupportedException(string .Format("常量{0}不支持" , c.Value)); default : sb.Append(c.Value); break ; } } return c; } protected override Expression VisitMember (MemberExpression m ) { if (m.Expression != null && m.Expression.NodeType == ExpressionType.Parameter) { sb.Append(m.Member.Name); return m; } throw new NotSupportedException(string .Format("成员{0}不支持" , m.Member.Name)); } }
修改表达式树 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class OperationsVisitor : ExpressionVisitor { public Expression Modify (Expression expression ) { return this .Visit(expression); } protected override Expression VisitBinary (BinaryExpression b ) { if (b.NodeType == ExpressionType.Add) { Expression left = this .Visit(b.Left); Expression right = this .Visit(b.Right); return Expression.Subtract(left,right); } return base .VisitBinary(b); } } static void Main (string [] args ){ Expression<Func<int , int , int >> lambda = (a, b) => a + b * 2 ; var operationsVisitor = new OperationsVisitor(); Expression modifyExpression = operationsVisitor.Modify(lambda); Console.WriteLine(modifyExpression.ToString()); }
参考:
表达式树
ExpressionVisitor
System.Linq.Expressions
由浅入深表达式树(二)遍历表达式树