1 public class SqlExpressionTree
2 {
3 public string GetQuerySql<T>(Expression<Func<T, bool>> condi)
4 {
5 string condition = "select * from "+typeof(T).Name+" "+ typeof(T).Name + " where ";
6 BinaryExpression body = (BinaryExpression)condi.Body;
7 condition+= GetSqlByExpression(body);
8 return condition;
9 }
10 /// <summary>
11 /// 通过Lambda解析为Sql
12 /// </summary>
13 /// <param name="func"></param>
14 /// <returns></returns>
15 public static string GetSqlByExpression(Expression func)
16 {
17 var funcType = CheckExpressionType(func);
18 switch (funcType)
19 {
20 case EnumNodeType.BinaryOperator:
21 return VisitBinaryExpression(func as BinaryExpression);
22 case EnumNodeType.Constant:
23 return VisitConstantExpression(func as ConstantExpression);
24 case EnumNodeType.Call:
25 return VisitMethodCallExpression(func as MethodCallExpression);
26 case EnumNodeType.UndryOperator:
27 return VisitUnaryExpression(func as UnaryExpression);
28 case EnumNodeType.MemberAccess:
29 return VisitMemberAccessExpression(func as MemberExpression);
30 default:
31 throw new NotSupportedException("不支持的操作在表达式处理中:");
32 }
33 }
34 public string CheckExpression(Expression exp)
35 {
36 string leftClude = "", rightClude = "";
37 if (exp.ToString().IndexOf("((") == 0)
38 {
39 leftClude = "("; rightClude = ")";
40 }
41 if (exp.NodeType == ExpressionType.MemberAccess || exp.NodeType == ExpressionType.Constant)
42 {
43 return exp.ToString();
44 }
45 if (exp as MethodCallExpression == null && exp as BinaryExpression == null)
46 throw new ArgumentException("不支持表达式的类型", "exp");
47 if (exp as MethodCallExpression != null)
48 {
49 MethodCallExpression cexp = exp as MethodCallExpression;
50 return "";
51 }
52 else
53 {
54 switch (exp.NodeType)
55 {
56 case ExpressionType.Equal:
57 return leftClude + CheckExpression(((BinaryExpression)exp).Left) + " = " + CheckExpression(((BinaryExpression)exp).Right) + rightClude;
58 case ExpressionType.Or:
59 return leftClude + CheckExpression(((BinaryExpression)exp).Left) + " or " + CheckExpression(((BinaryExpression)exp).Right) + rightClude;
60 case ExpressionType.OrElse:
61 return leftClude + CheckExpression(((BinaryExpression)exp).Left) + " or " + CheckExpression(((BinaryExpression)exp).Right) + rightClude;
62 case ExpressionType.AndAlso:
63 return leftClude + CheckExpression(((BinaryExpression)exp).Left) + " and " + CheckExpression(((BinaryExpression)exp).Right) + rightClude;
64 default:
65 return "";
66 }
67 }
68 }
69 /// <summary>
70 /// 判断表达式类型
71 /// </summary>
72 /// <param name="func">lambda表达式</param>
73 /// <returns></returns>
74 private static EnumNodeType CheckExpressionType(Expression func)
75 {
76 switch (func.NodeType)
77 {
78 case ExpressionType.AndAlso:
79 case ExpressionType.OrElse:
80 case ExpressionType.Equal:
81 case ExpressionType.GreaterThanOrEqual:
82 case ExpressionType.LessThanOrEqual:
83 case ExpressionType.GreaterThan:
84 case ExpressionType.LessThan:
85 case ExpressionType.NotEqual:
86 return EnumNodeType.BinaryOperator;
87 case ExpressionType.Constant:
88 return EnumNodeType.Constant;
89 case ExpressionType.MemberAccess:
90 return EnumNodeType.MemberAccess;
91 case ExpressionType.Call:
92 return EnumNodeType.Call;
93 case ExpressionType.Not:
94 case ExpressionType.Convert:
95 return EnumNodeType.UndryOperator;
96 default:
97 return EnumNodeType.Unknown;
98 }
99 }
100 private static string ExpressionTypeToString(ExpressionType type)
101 {
102 switch (type)
103 {
104 case ExpressionType.Equal:
105 return " = ";
106 case ExpressionType.Or:
107 return " or ";
108 case ExpressionType.OrElse:
109 return " or ";
110 case ExpressionType.AndAlso:
111 return " and ";
112 default:
113 return "";
114 }
115 }
116 /// <summary>
117 /// 判断一元表达式
118 /// </summary>
119 /// <param name="func"></param>
120 /// <returns></returns>
121 private static string VisitUnaryExpression(UnaryExpression func)
122 {
123 var result = ExpressionTypeToString(func.NodeType);
124 var funcType = CheckExpressionType(func.Operand);
125 switch (funcType)
126 {
127 case EnumNodeType.BinaryOperator:
128 return result + VisitBinaryExpression(func.Operand as BinaryExpression);
129 case EnumNodeType.Constant:
130 return result + VisitConstantExpression(func.Operand as ConstantExpression);
131 case EnumNodeType.Call:
132 return result + VisitMethodCallExpression(func.Operand as MethodCallExpression);
133 case EnumNodeType.UndryOperator:
134 return result + VisitUnaryExpression(func.Operand as UnaryExpression);
135 case EnumNodeType.MemberAccess:
136 return result + VisitMemberAccessExpression(func.Operand as MemberExpression);
137 default:
138 throw new NotSupportedException("不支持的操作在一元操作处理中:");
139 }
140 }
141
142 /// <summary>
143 /// 判断常量表达式
144 /// </summary>
145 /// <param name="func"></param>
146 /// <returns></returns>
147 private static string VisitConstantExpression(ConstantExpression func)
148 {
149 if (func.Value.ToString() == "")
150 {
151 return "\'\' ";
152 }
153 else if (func.Value.ToString() == "True")
154 {
155 return "1 = 1 ";
156 }
157 else if (func.Value.ToString() == "False")
158 {
159 return "0 = 1 ";
160 }
161 else
162 {
163 return "'" + func.Value.ToString() + "' ";
164
165 }
166 }
167
168 /// <summary>
169 /// 判断包含变量的表达式
170 /// </summary>
171 /// <param name="func"></param>
172 /// <returns></returns>
173 private static string VisitMemberAccessExpression(MemberExpression func)
174 {
175 try
176 {
177 var tablename = func.Expression.Type.Name;
178 return tablename + "." + func.Member.Name + " ";
179 }
180 catch
181 {
182 object value;
183 switch (func.Type.Name)
184 {
185 case "Int32":
186 {
187 var getter = Expression.Lambda<Func<int>>(func).Compile();
188 value = getter();
189 }
190 break;
191 case "String":
192 {
193 var getter = Expression.Lambda<Func<string>>(func).Compile();
194 value = "'" + getter() + "'";
195 }
196 break;
197 case "DateTime":
198 {
199 var getter = Expression.Lambda<Func<DateTime>>(func).Compile();
200 value = "'" + getter() + "'";
201 }
202 break;
203 default:
204 {
205 var getter = Expression.Lambda<Func<object>>(func).Compile();
206 value = getter();
207 }
208 break;
209 }
210 return value.ToString();
211 }
212 }
213 /// <summary>
214 /// 判断包含函数的表达式
215 /// </summary>
216 /// <param name="func"></param>
217 /// <returns></returns>
218 private static String VisitMethodCallExpression(MethodCallExpression func)
219 {
220 if (func.Method.Name.Contains("Contains"))
221 {
222 if (func.Object.Type.Name.ToLower() == "string")
223 {
224 //获得调用者的内容元素
225 var field = VisitMemberAccessExpression(func.Object as MemberExpression);
226 //获得字段
227 var caller = func.Arguments[0];
228 var param = Expression.Lambda<Func<object>>(caller).Compile();
229 return field + " like '%" + param() + "%'";
230 }
231 else
232 {
233 //获得调用者的内容元素
234 var getter = Expression.Lambda<Func<object>>(func.Object).Compile();
235 var data = getter() as IEnumerable;
236 //获得字段
237 var caller = func.Arguments[0];
238 while (caller.NodeType == ExpressionType.Call)
239 {
240 caller = (caller as MethodCallExpression).Object;
241 }
242 var field = VisitMemberAccessExpression(caller as MemberExpression);
243 var list = (from object i in data select "'" + i + "'").ToList();
244 return field + " IN (" + string.Join(",", list.Cast<string>().ToArray()) + ") ";
245 }
246 }
247 else
248 {
249 throw new NotSupportedException("不支持的函数操作:" + func.Method.Name);
250 }
251 }
252 /// <summary>
253 /// 判断包含二元运算符的表达式
254 /// </summary>
255 /// <remarks>注意,这个函数使用了递归,修改时注意不要修改了代码顺序和逻辑</remarks>
256 /// <param name="func"></param>
257 private static string VisitBinaryExpression(BinaryExpression func)
258 {
259 var result = "(";
260 var leftType = CheckExpressionType(func.Left);
261 switch (leftType)
262 {
263 case EnumNodeType.BinaryOperator:
264 result += VisitBinaryExpression(func.Left as BinaryExpression); break;
265 case EnumNodeType.Constant:
266 result += VisitConstantExpression(func.Left as ConstantExpression); break;
267 case EnumNodeType.MemberAccess:
268 result += VisitMemberAccessExpression(func.Left as MemberExpression); break;
269 case EnumNodeType.UndryOperator:
270 result += VisitUnaryExpression(func.Left as UnaryExpression); break;
271 case EnumNodeType.Call:
272 result += VisitMethodCallExpression(func.Left as MethodCallExpression); break;
273 default:
274 throw new NotSupportedException("不支持的操作在二元操作处理中:");
275 }
276
277 result += ExpressionTypeToString(func.NodeType) + " ";
278
279 var rightType = CheckExpressionType(func.Right);
280 switch (rightType)
281 {
282 case EnumNodeType.BinaryOperator:
283 result += VisitBinaryExpression(func.Right as BinaryExpression); break;
284 case EnumNodeType.Constant:
285 result += VisitConstantExpression(func.Right as ConstantExpression); break;
286 case EnumNodeType.MemberAccess:
287 result += VisitMemberAccessExpression(func.Right as MemberExpression); break;
288 case EnumNodeType.UndryOperator:
289 result += VisitUnaryExpression(func.Right as UnaryExpression); break;
290 case EnumNodeType.Call:
291 result += VisitMethodCallExpression(func.Right as MethodCallExpression); break;
292 default:
293 throw new NotSupportedException("不支持的操作在二元操作处理中:");
294 }
295
296 result += ") ";
297 return result;
298 }
299 }
300
301
302 public enum EnumNodeType
303 {
304 [Description("二元运算符")]
305 BinaryOperator = 1,
306 [Description("一元运算符")]
307 UndryOperator = 2,
308 [Description("常量表达式")]
309 Constant = 3,
310 [Description("成员(变量)")]
311 MemberAccess = 4,
312 [Description("函数")]
313 Call = 5,
314 [Description("未知")]
315 Unknown = -99,
316 [Description("不支持")]
317 NotSupported = -98
318 }