MappingObjectExpression.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. using Ant.Extensions;
  2. using Ant.DbExpressions;
  3. using Ant.Descriptors;
  4. using Ant.Query.Mapping;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Linq.Expressions;
  9. using System.Reflection;
  10. using Ant.Utility;
  11. namespace Ant.Query
  12. {
  13. public class MappingObjectExpression : IMappingObjectExpression
  14. {
  15. public MappingObjectExpression(ConstructorInfo constructor)
  16. : this(EntityConstructorDescriptor.GetInstance(constructor))
  17. {
  18. }
  19. public MappingObjectExpression(EntityConstructorDescriptor constructorDescriptor)
  20. {
  21. this.ConstructorDescriptor = constructorDescriptor;
  22. this.ConstructorParameters = new Dictionary<ParameterInfo, DbExpression>();
  23. this.ConstructorEntityParameters = new Dictionary<ParameterInfo, IMappingObjectExpression>();
  24. this.SelectedMembers = new Dictionary<MemberInfo, DbExpression>();
  25. this.SubResultEntities = new Dictionary<MemberInfo, IMappingObjectExpression>();
  26. }
  27. public DbExpression PrimaryKey { get; set; }
  28. public DbExpression NullChecking { get; set; }
  29. /// <summary>
  30. /// 返回类型
  31. /// </summary>
  32. public EntityConstructorDescriptor ConstructorDescriptor { get; private set; }
  33. public Dictionary<ParameterInfo, DbExpression> ConstructorParameters { get; private set; }
  34. public Dictionary<ParameterInfo, IMappingObjectExpression> ConstructorEntityParameters { get; private set; }
  35. public Dictionary<MemberInfo, DbExpression> SelectedMembers { get; protected set; }
  36. public Dictionary<MemberInfo, IMappingObjectExpression> SubResultEntities { get; protected set; }
  37. public void AddConstructorParameter(ParameterInfo p, DbExpression exp)
  38. {
  39. this.ConstructorParameters.Add(p, exp);
  40. }
  41. public void AddConstructorEntityParameter(ParameterInfo p, IMappingObjectExpression exp)
  42. {
  43. this.ConstructorEntityParameters.Add(p, exp);
  44. }
  45. public void AddMemberExpression(MemberInfo m, DbExpression exp)
  46. {
  47. this.SelectedMembers.Add(m, exp);
  48. }
  49. public void AddNavMemberExpression(MemberInfo p, IMappingObjectExpression exp)
  50. {
  51. this.SubResultEntities.Add(p, exp);
  52. }
  53. /// <summary>
  54. /// 考虑匿名函数构造函数参数和其只读属性的对应
  55. /// </summary>
  56. /// <param name="memberInfo"></param>
  57. /// <returns></returns>
  58. public DbExpression GetMemberExpression(MemberInfo memberInfo)
  59. {
  60. DbExpression ret = null;
  61. if (!this.SelectedMembers.TryGetValue(memberInfo, out ret))
  62. {
  63. ParameterInfo p = null;
  64. if (!this.ConstructorDescriptor.MemberParameterMap.TryGetValue(memberInfo, out p))
  65. {
  66. return null;
  67. }
  68. if (!this.ConstructorParameters.TryGetValue(p, out ret))
  69. {
  70. return null;
  71. }
  72. }
  73. return ret;
  74. }
  75. public IMappingObjectExpression GetNavMemberExpression(MemberInfo memberInfo)
  76. {
  77. IMappingObjectExpression ret = null;
  78. if (!this.SubResultEntities.TryGetValue(memberInfo, out ret))
  79. {
  80. //从构造函数中查
  81. ParameterInfo p = null;
  82. if (!this.ConstructorDescriptor.MemberParameterMap.TryGetValue(memberInfo, out p))
  83. {
  84. return null;
  85. }
  86. if (!this.ConstructorEntityParameters.TryGetValue(p, out ret))
  87. {
  88. return null;
  89. }
  90. }
  91. return ret;
  92. }
  93. public DbExpression GetDbExpression(MemberExpression memberExpressionDeriveParameter)
  94. {
  95. Stack<MemberExpression> memberExpressions = ExpressionExtensions.Reverse(memberExpressionDeriveParameter);
  96. DbExpression ret = null;
  97. IMappingObjectExpression moe = this;
  98. foreach (MemberExpression memberExpression in memberExpressions)
  99. {
  100. MemberInfo member = memberExpression.Member;
  101. if (moe == null && ret != null)
  102. {
  103. /* a.F_DateTime.Value.Date */
  104. ret = DbExpression.MemberAccess(member, ret);
  105. continue;
  106. }
  107. DbExpression e = moe.GetMemberExpression(member);
  108. if (e == null)
  109. {
  110. moe = moe.GetNavMemberExpression(member);
  111. if (moe == null)
  112. {
  113. if (ret == null)
  114. {
  115. throw new Exception();
  116. }
  117. else
  118. {
  119. ret = DbExpression.MemberAccess(member, ret);
  120. continue;
  121. }
  122. }
  123. if (ret != null)
  124. throw new NotSupportedException(memberExpressionDeriveParameter.ToString());
  125. }
  126. else
  127. {
  128. if (ret != null)
  129. throw new NotSupportedException(memberExpressionDeriveParameter.ToString());
  130. ret = e;
  131. }
  132. }
  133. if (ret == null)
  134. throw new Exception(memberExpressionDeriveParameter.ToString());
  135. return ret;
  136. }
  137. public IMappingObjectExpression GetNavMemberExpression(MemberExpression memberExpressionDeriveParameter)
  138. {
  139. Stack<MemberExpression> memberExpressions = ExpressionExtensions.Reverse(memberExpressionDeriveParameter);
  140. if (memberExpressions.Count == 0)
  141. throw new Exception();
  142. IMappingObjectExpression ret = this;
  143. foreach (MemberExpression memberExpression in memberExpressions)
  144. {
  145. MemberInfo member = memberExpression.Member;
  146. ret = ret.GetNavMemberExpression(member);
  147. if (ret == null)
  148. {
  149. throw new NotSupportedException(memberExpressionDeriveParameter.ToString());
  150. }
  151. }
  152. return ret;
  153. }
  154. public IObjectActivatorCreator GenarateObjectActivatorCreator(DbSqlQueryExpression sqlQuery)
  155. {
  156. List<DbColumnSegment> columnList = sqlQuery.ColumnSegments;
  157. MappingEntity mappingEntity = new MappingEntity(this.ConstructorDescriptor);
  158. MappingObjectExpression mappingMembers = this;
  159. foreach (var kv in this.ConstructorParameters)
  160. {
  161. ParameterInfo pi = kv.Key;
  162. DbExpression exp = kv.Value;
  163. int ordinal;
  164. ordinal = MappingObjectExpressionHelper.TryGetOrAddColumn(sqlQuery, exp, pi.Name).Value;
  165. if (exp == this.NullChecking)
  166. mappingEntity.CheckNullOrdinal = ordinal;
  167. mappingEntity.ConstructorParameters.Add(pi, ordinal);
  168. }
  169. foreach (var kv in mappingMembers.ConstructorEntityParameters)
  170. {
  171. ParameterInfo pi = kv.Key;
  172. IMappingObjectExpression val = kv.Value;
  173. IObjectActivatorCreator navMappingMember = val.GenarateObjectActivatorCreator(sqlQuery);
  174. mappingEntity.ConstructorEntityParameters.Add(pi, navMappingMember);
  175. }
  176. foreach (var kv in mappingMembers.SelectedMembers)
  177. {
  178. MemberInfo member = kv.Key;
  179. DbExpression exp = kv.Value;
  180. int ordinal;
  181. ordinal = MappingObjectExpressionHelper.TryGetOrAddColumn(sqlQuery, exp, member.Name).Value;
  182. if (exp == this.NullChecking)
  183. mappingEntity.CheckNullOrdinal = ordinal;
  184. mappingEntity.Members.Add(member, ordinal);
  185. }
  186. foreach (var kv in mappingMembers.SubResultEntities)
  187. {
  188. MemberInfo member = kv.Key;
  189. IMappingObjectExpression val = kv.Value;
  190. IObjectActivatorCreator navMappingMember = val.GenarateObjectActivatorCreator(sqlQuery);
  191. mappingEntity.EntityMembers.Add(kv.Key, navMappingMember);
  192. }
  193. if (mappingEntity.CheckNullOrdinal == null)
  194. mappingEntity.CheckNullOrdinal = MappingObjectExpressionHelper.TryGetOrAddColumn(sqlQuery, this.NullChecking);
  195. return mappingEntity;
  196. }
  197. public IMappingObjectExpression ToNewObjectExpression(DbSqlQueryExpression sqlQuery, DbTable table)
  198. {
  199. List<DbColumnSegment> columnList = sqlQuery.ColumnSegments;
  200. MappingObjectExpression moe = new MappingObjectExpression(this.ConstructorDescriptor);
  201. MappingObjectExpression mappingMembers = this;
  202. foreach (var kv in this.ConstructorParameters)
  203. {
  204. ParameterInfo pi = kv.Key;
  205. DbExpression exp = kv.Value;
  206. DbColumnAccessExpression cae = null;
  207. cae = MappingObjectExpressionHelper.ParseColumnAccessExpression(sqlQuery, table, exp, pi.Name);
  208. moe.AddConstructorParameter(pi, cae);
  209. }
  210. foreach (var kv in mappingMembers.ConstructorEntityParameters)
  211. {
  212. ParameterInfo pi = kv.Key;
  213. IMappingObjectExpression val = kv.Value;
  214. IMappingObjectExpression navMappingMember = val.ToNewObjectExpression(sqlQuery, table);
  215. moe.AddConstructorEntityParameter(pi, navMappingMember);
  216. }
  217. foreach (var kv in mappingMembers.SelectedMembers)
  218. {
  219. MemberInfo member = kv.Key;
  220. DbExpression exp = kv.Value;
  221. DbColumnAccessExpression cae = null;
  222. cae = MappingObjectExpressionHelper.ParseColumnAccessExpression(sqlQuery, table, exp, member.Name);
  223. moe.AddMemberExpression(member, cae);
  224. if (exp == this.PrimaryKey)
  225. {
  226. moe.PrimaryKey = cae;
  227. if (this.NullChecking == this.PrimaryKey)
  228. moe.NullChecking = cae;
  229. }
  230. }
  231. foreach (var kv in mappingMembers.SubResultEntities)
  232. {
  233. MemberInfo member = kv.Key;
  234. IMappingObjectExpression val = kv.Value;
  235. IMappingObjectExpression navMappingMember = val.ToNewObjectExpression(sqlQuery, table);
  236. moe.AddNavMemberExpression(member, navMappingMember);
  237. }
  238. if (moe.NullChecking == null)
  239. moe.NullChecking = MappingObjectExpressionHelper.TryGetOrAddNullChecking(sqlQuery, table, this.NullChecking);
  240. return moe;
  241. }
  242. public void SetNullChecking(DbExpression exp)
  243. {
  244. if (this.NullChecking == null)
  245. {
  246. if (this.PrimaryKey != null)
  247. this.NullChecking = this.PrimaryKey;
  248. else
  249. this.NullChecking = exp;
  250. }
  251. foreach (var item in this.ConstructorEntityParameters.Values)
  252. {
  253. item.SetNullChecking(exp);
  254. }
  255. foreach (var item in this.SubResultEntities.Values)
  256. {
  257. item.SetNullChecking(exp);
  258. }
  259. }
  260. }
  261. }