PageRenderTime 57ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/UnifyShow/NRemedy/Extension/QueryVisitor.cs

http://fjycUnifyShow.codeplex.com
C# | 267 lines | 183 code | 29 blank | 55 comment | 43 complexity | 61c23c7a3cba49236c16d623c0253d94 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Linq.Expressions;
  6. using System.Reflection;
  7. namespace NRemedy.Linq
  8. {
  9. public class QueryVisitor : ExpressionVisitor
  10. {
  11. StringBuilder sb;
  12. TranslateResult tr;
  13. //indicate method stack , in order to tell which method is in when visit(),may be:
  14. Stack<string> methods = new Stack<string>();
  15. public QueryVisitor(){
  16. tr = new TranslateResult();
  17. }
  18. internal TranslateResult Translate(Expression expression)
  19. {
  20. this.sb = new StringBuilder();
  21. this.Visit(expression);
  22. return tr;
  23. }
  24. private static Expression StripQuotes(Expression e) {
  25. while (e.NodeType == ExpressionType.Quote) {
  26. e = ((UnaryExpression)e).Operand;
  27. }
  28. return e;
  29. }
  30. protected override Expression VisitMethodCall(MethodCallExpression m) {
  31. if (m.Method.DeclaringType == typeof(Queryable) && m.Method.Name == "Where") {
  32. methods.Push("Where");
  33. this.Visit(m.Arguments[0]);
  34. LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);
  35. this.Visit(lambda.Body);
  36. methods.Pop();
  37. return m;
  38. }
  39. else if (m.Method.DeclaringType == typeof(Queryable) && m.Method.Name == "Select")
  40. {
  41. methods.Push("Select");
  42. this.Visit(m.Arguments[0]);
  43. LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);
  44. tr.SelectExpression = lambda;
  45. tr.Select = true;
  46. this.Visit(lambda.Body);
  47. methods.Pop();
  48. return m;
  49. }
  50. else if (m.Method.DeclaringType == typeof(Queryable) && m.Method.Name == "Count")
  51. {
  52. tr.Count = true;
  53. this.Visit(m.Arguments[0]);
  54. if (m.Arguments.Count == 2)
  55. {
  56. //LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);
  57. //this.Visit(lambda.Body);
  58. throw new NotSupportedException("Count clause not support parameter,use where clause instead.");
  59. }
  60. return m;
  61. }
  62. throw new NotSupportedException(string.Format("The method '{0}' is not supported", m.Method.Name));
  63. }
  64. protected override Expression VisitUnary(UnaryExpression u) {
  65. switch (u.NodeType) {
  66. case ExpressionType.Not:
  67. sb.Append(" NOT ");
  68. this.Visit(u.Operand);
  69. break;
  70. case ExpressionType.Convert:
  71. return this.Visit(u.Operand);
  72. default:
  73. throw new NotSupportedException(string.Format("The unary operator '{0}' is not supported", u.NodeType));
  74. }
  75. return u;
  76. }
  77. protected override Expression VisitBinary(BinaryExpression b) {
  78. tr.Qulification.Append("(");
  79. Expression eTmp = this.Visit(b.Left);
  80. switch (b.NodeType) {
  81. case ExpressionType.AndAlso:
  82. case ExpressionType.And:
  83. tr.Qulification.Append(" AND ");
  84. break;
  85. case ExpressionType.Or:
  86. case ExpressionType.OrElse:
  87. tr.Qulification.Append(" OR ");
  88. break;
  89. case ExpressionType.Equal:
  90. tr.Qulification.Append(" = ");
  91. break;
  92. case ExpressionType.NotEqual:
  93. tr.Qulification.Append(" != ");
  94. break;
  95. case ExpressionType.LessThan:
  96. tr.Qulification.Append(" < ");
  97. break;
  98. case ExpressionType.LessThanOrEqual:
  99. tr.Qulification.Append(" <= ");
  100. break;
  101. case ExpressionType.GreaterThan:
  102. tr.Qulification.Append(" > ");
  103. break;
  104. case ExpressionType.GreaterThanOrEqual:
  105. tr.Qulification.Append(" >= ");
  106. break;
  107. default:
  108. throw new NotSupportedException(string.Format("The binary operator '{0}' is not supported", b.NodeType));
  109. }
  110. if (b.Right.NodeType == ExpressionType.Constant && eTmp.NodeType == ExpressionType.MemberAccess){
  111. VisitConstant((ConstantExpression)b.Right, (MemberExpression)eTmp);
  112. }
  113. else
  114. this.Visit(b.Right);
  115. tr.Qulification.Append(")");
  116. return b;
  117. }
  118. private Expression VisitConstant(ConstantExpression c,MemberExpression me) {
  119. if (me.Type.IsEnum)
  120. return Visit(Expression.Constant(Enum.GetName(me.Type, c.Value)));
  121. else
  122. return Visit(c);
  123. }
  124. protected override Expression VisitConstant(ConstantExpression c) {
  125. IQueryable q = c.Value as IQueryable;
  126. if (q != null) {
  127. // assume constant nodes w/ IQueryables are table references
  128. //store Generic Type
  129. //tr.ModelType = q.ElementType;
  130. }
  131. else if (c.Value == null) {
  132. tr.Qulification.Append("$NULL$");
  133. }
  134. else {
  135. switch (Type.GetTypeCode(c.Value.GetType())) {
  136. case TypeCode.String:
  137. tr.Qulification.Append("\"");
  138. tr.Qulification.Append(c.Value);
  139. tr.Qulification.Append("\"");
  140. break;
  141. case TypeCode.DateTime:
  142. tr.Qulification.Append("\"");
  143. tr.Qulification.Append(((DateTime)c.Value).ToString());
  144. tr.Qulification.Append("\"");
  145. break;
  146. case TypeCode.Int32:
  147. case TypeCode.Int16:
  148. case TypeCode.Int64:
  149. case TypeCode.Decimal:
  150. case TypeCode.Double:
  151. tr.Qulification.Append(c.Value);
  152. break;
  153. default:
  154. throw new NotSupportedException(string.Format("The constant for '{0}' is not supported", c.Value));
  155. }
  156. }
  157. return c;
  158. }
  159. protected override Expression VisitMember(MemberExpression node)
  160. {
  161. if (methods.Peek() == "Where")
  162. {
  163. if (node.Member == null) return node;
  164. object[] attrs = node.Member.GetCustomAttributes(typeof(ARFieldAttribute), true);
  165. if (attrs.Length > 1)
  166. throw new CustomAttributeFormatException(
  167. string.Format("Mutiple ARFieldAttribute is found on Property : {0}.", node.Member.Name));
  168. if (attrs.Length == 0)
  169. throw new CustomAttributeFormatException(
  170. string.Format("No ARFieldAttribute is found on Property : {0}.", node.Member.Name));
  171. ARFieldAttribute attr = (ARFieldAttribute)attrs.First();
  172. string arFieldName = attr.DatabaseID.ToString();
  173. if (string.IsNullOrEmpty(arFieldName)) throw new CustomAttributeFormatException(
  174. string.Format("DatabaseName in ARFieldAttribute is found on Property : {0}.", node.Member.Name)
  175. );
  176. tr.Qulification.Append("'");
  177. tr.Qulification.Append(arFieldName);
  178. tr.Qulification.Append("'");
  179. }
  180. else if (methods.Peek() == "Select")
  181. {
  182. tr.SelectedProperties.Add(new MemberMap {
  183. SourceMemberName = node.Member.Name
  184. });
  185. }
  186. return node;
  187. }
  188. //protected override Expression VisitMemberInit(MemberInitExpression node)
  189. //{
  190. // //only select clause may visit member init
  191. // if(methods.Peek() == "Select")
  192. // {
  193. // tr.TargetType = node.Type;
  194. // foreach (var bind in node.Bindings)
  195. // {
  196. // if (bind.BindingType == MemberBindingType.Assignment)
  197. // {
  198. // MemberAssignment ma = bind as MemberAssignment;
  199. // MemberMap memberMap = new MemberMap();
  200. // if(ma == null)
  201. // throw new NullReferenceException("bind");
  202. // memberMap.TargetMemberName = ma.Member.Name;
  203. // if(!(ma.Expression is MemberExpression))
  204. // throw new NotImplementedException("Non-MemberExpression is not support yet.");
  205. // memberMap.SourceMemberName = (ma.Expression as MemberExpression).Member.Name;
  206. // tr.SelectedProperties.Add(memberMap);
  207. // }
  208. // else if(bind.BindingType == MemberBindingType.ListBinding)
  209. // {
  210. // throw new NotImplementedException("MemberBindingType.ListBinding is not support yet.");
  211. // }
  212. // else if (bind.BindingType == MemberBindingType.MemberBinding)
  213. // {
  214. // throw new NotImplementedException("MemberBindingType.MemberBinding is not support yet.");
  215. // }
  216. // }
  217. // }
  218. // return node;
  219. //}
  220. //protected override Expression VisitNew(NewExpression node)
  221. //{
  222. // //only select clause may visit member init
  223. // if (methods.Peek() == "Select")
  224. // {
  225. // tr.TargetType = node.Type;
  226. // for (int i = 0; i < node.Members.Count; i++)
  227. // {
  228. // MemberMap memberMap = new MemberMap();
  229. // //memberMap.TargetMemberName = node.Members[i].Name;
  230. // //if(!(node.Arguments[i].Type is MemberExpression))
  231. // // throw new NotImplementedException("Non-MemberExpression is not support yet.");
  232. // // memberMap.SourceMemberName = (ma.Expression as MemberExpression).Member.Name;
  233. // }
  234. // }
  235. // return node;
  236. //}
  237. }
  238. }