MapperConfigurationBase.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. using Masuit.Tools.Mapping.Exceptions;
  2. using Masuit.Tools.Mapping.Helper;
  3. using Masuit.Tools.Mapping.Visitor;
  4. using System;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.Linq;
  9. using System.Linq.Expressions;
  10. using System.Reflection;
  11. namespace Masuit.Tools.Mapping.Core
  12. {
  13. /// <summary>
  14. /// mapper配置基类
  15. /// </summary>
  16. public abstract class MapperConfigurationBase
  17. {
  18. private Delegate _delegateCallForNew;
  19. private Delegate _delegateCallForExisting;
  20. private Func<Type, object> _constructorFunc;
  21. private bool _isInitialized;
  22. private readonly MethodInfo _selectMethod;
  23. private readonly MethodInfo _toListMethod;
  24. private readonly List<PropertyInfo> _propertiesToIgnore;
  25. internal ParameterExpression paramClassSource;
  26. internal MapperExpressionVisitor visitorMapper;
  27. internal List<MemberAssignment> memberForNew;
  28. internal LambdaExpression expressionForExisting;
  29. /// <summary>
  30. /// 属性映射对应关系<br/>
  31. /// Item1 : 源表达式<br/>
  32. /// Item2 : 目标表达式<br/>
  33. /// Item3 : 检查null值<br/>
  34. /// Item4 : mapper别名<br/>
  35. /// </summary>
  36. protected List<Tuple<Expression, Expression, bool, string>> PropertiesMapping { get; private set; }
  37. /// <summary>
  38. /// 需要被忽略映射的属性
  39. /// </summary>
  40. protected ReadOnlyCollection<PropertyInfo> PropertiesToIgnore => _propertiesToIgnore.AsReadOnly();
  41. /// <summary>
  42. /// 是否使用服务依赖注入
  43. /// </summary>
  44. public bool UseServiceLocator { get; protected set; }
  45. /// <summary>
  46. /// 对象源类型
  47. /// </summary>
  48. public Type SourceType { get; private set; }
  49. /// <summary>
  50. /// 对象目标类型
  51. /// </summary>
  52. public Type TargetType { get; private set; }
  53. /// <summary>
  54. /// 获取mapper映射成员
  55. /// </summary>
  56. public ReadOnlyCollection<MemberAssignment> MemberToMapForNew => new ReadOnlyCollection<MemberAssignment>(memberForNew);
  57. /// <summary>
  58. /// mapper别名
  59. /// </summary>
  60. public string Name { get; protected set; }
  61. /// <summary>
  62. /// 构造函数
  63. /// </summary>
  64. /// <param name="source">源类型</param>
  65. /// <param name="destination">目标类型</param>
  66. /// <param name="paramName">属性名</param>
  67. /// <param name="name">别名</param>
  68. protected MapperConfigurationBase(Type source, Type destination, string paramName, string name = null)
  69. {
  70. TargetType = destination;
  71. SourceType = source;
  72. paramClassSource = Expression.Parameter(source, paramName);
  73. Name = string.IsNullOrEmpty(name) ? paramName : name;
  74. _propertiesToIgnore = new List<PropertyInfo>();
  75. PropertiesMapping = new List<Tuple<Expression, Expression, bool, string>>();
  76. visitorMapper = new MapperExpressionVisitor(paramClassSource);
  77. memberForNew = new List<MemberAssignment>();
  78. _selectMethod = typeof(Enumerable).GetMethods().Where(m => m.Name == "Select").Select(x => x.GetParameters().First(p => p.Name.Equals("selector") && p.ParameterType.GetGenericArguments().Length == 2)).First().Member as MethodInfo;
  79. _toListMethod = typeof(Enumerable).GetMethod("ToList");
  80. }
  81. /// <summary>
  82. /// 获取mapper委托
  83. /// </summary>
  84. /// <returns></returns>
  85. public Delegate GetDelegate()
  86. {
  87. if (!_isInitialized)
  88. {
  89. throw new MapperNotInitializedException(SourceType, TargetType);
  90. }
  91. // 因为在这里有映射器的性能问题,而缓存委托会显着缩短处理时间,如果没有表达式编译每次编译会很慢
  92. if (_delegateCallForNew == null)
  93. {
  94. MemberInitExpression exp = GetMemberInitExpression();
  95. _delegateCallForNew = Expression.Lambda(exp, paramClassSource).Compile();
  96. }
  97. return _delegateCallForNew;
  98. }
  99. /// <summary>
  100. /// 获取现有目标类型的委托。
  101. /// </summary>
  102. /// <exception cref="MapperNotInitializedException"></exception>
  103. public Delegate GetDelegateForExistingTarget()
  104. {
  105. if (!_isInitialized)
  106. {
  107. throw new MapperNotInitializedException(SourceType, TargetType);
  108. }
  109. // 因为在这里有映射器的性能问题,而缓存委托会显着缩短处理时间,如果没有表达式编译每次编译会很慢
  110. if (_delegateCallForExisting == null)
  111. {
  112. CreateMemberAssignementForExistingTarget();
  113. }
  114. return _delegateCallForExisting;
  115. }
  116. /// <summary>
  117. /// 获取泛型的Lambda表达式
  118. /// </summary>
  119. public LambdaExpression GetGenericLambdaExpression()
  120. {
  121. MemberInitExpression exp = GetMemberInitExpression();
  122. return Expression.Lambda(exp, paramClassSource);
  123. }
  124. /// <summary>
  125. /// 获取目标类型的实际类型
  126. /// </summary>
  127. public Type GetDestinationType()
  128. {
  129. return GetRealType(TargetType);
  130. }
  131. /// <summary>
  132. /// 忽略目标类型的属性
  133. /// </summary>
  134. /// <typeparam name="TDest">对象源类型</typeparam>
  135. /// <typeparam name="TProperty">对象目标类型</typeparam>
  136. /// <param name="propertyDest">目标对象的属性</param>
  137. /// <returns></returns>
  138. protected MapperConfigurationBase IgnoreBase<TDest, TProperty>(Expression<Func<TDest, TProperty>> propertyDest)
  139. {
  140. // 添加到映射列表并且可以继续操作
  141. _propertiesToIgnore.Add(GetPropertyInfo(propertyDest));
  142. return this;
  143. }
  144. /// <summary>
  145. /// 获取映射器实例
  146. /// </summary>
  147. /// <param name="typeOfSource">源类型</param>
  148. /// <param name="typeOfTarget">目标类型</param>
  149. /// <param name="throwExceptionOnNoFound">如果没找到是否需要抛出异常</param>
  150. /// <param name="name">mapper别名</param>
  151. /// <returns></returns>
  152. /// <exception cref="NoFoundMapperException"></exception>
  153. protected static MapperConfigurationBase GetMapper(Type typeOfSource, Type typeOfTarget, bool throwExceptionOnNoFound, string name = null)
  154. {
  155. var mapperExterne = MapperConfigurationCollectionContainer.Instance.Find(typeOfSource, typeOfTarget, name);
  156. // 如果没有任何配置,手动抛出异常
  157. if (mapperExterne == null && throwExceptionOnNoFound)
  158. {
  159. throw new NoFoundMapperException(typeOfSource, typeOfTarget);
  160. }
  161. return mapperExterne;
  162. }
  163. /// <summary>
  164. /// 创建公共成员
  165. /// </summary>
  166. protected void CreateCommonMember()
  167. {
  168. PropertyInfo[] propertiesSource = SourceType.GetProperties();
  169. foreach (PropertyInfo propSource in propertiesSource)
  170. {
  171. PropertyInfo propDest = TargetType.GetProperty(propSource.Name);
  172. if (propDest != null)
  173. {
  174. // 检查是否已存在或被忽略。
  175. bool ignorePropDest = _propertiesToIgnore.Exists(x => x.Name == propDest.Name) || PropertiesMapping.Exists(x => GetPropertyInfo(x.Item2).Name == propDest.Name);
  176. if (propDest.CanWrite && !ignorePropDest)
  177. {
  178. Type sourceType = propSource.PropertyType;
  179. Type destType = propDest.PropertyType;
  180. bool isList = IsListOf(destType);
  181. if (isList)
  182. {
  183. sourceType = TypeSystem.GetElementType(propSource.PropertyType);
  184. destType = TypeSystem.GetElementType(propDest.PropertyType);
  185. }
  186. var canCreateConfig = CanCreateConfig(sourceType, destType);
  187. if (canCreateConfig.CanCreate)
  188. {
  189. // 只创造现有的关系
  190. Expression expSource = Expression.MakeMemberAccess(paramClassSource, propSource);
  191. ParameterExpression paramDest = Expression.Parameter(TargetType, "t");
  192. Expression expDest = Expression.MakeMemberAccess(paramDest, propDest);
  193. PropertiesMapping.Add(Tuple.Create(expSource, expDest, false, canCreateConfig.MapperName));
  194. }
  195. }
  196. }
  197. }
  198. }
  199. private static CreateConfig CanCreateConfig(Type typeSource, Type typeTarget)
  200. {
  201. CreateConfig result = new CreateConfig
  202. {
  203. CanCreate = typeSource == typeTarget
  204. };
  205. //不是同一类型
  206. if (!result.CanCreate)
  207. {
  208. //查找是否存在映射器
  209. var mapper = MapperConfigurationCollectionContainer.Instance.Find(typeSource, typeTarget);
  210. if (mapper != null)
  211. {
  212. result.MapperName = mapper.Name;
  213. result.CanCreate = true;
  214. }
  215. }
  216. return result;
  217. }
  218. /// <summary>
  219. /// 检查并配置mapper
  220. /// </summary>
  221. /// <param name="configExpression">配置表达式树</param>
  222. /// <exception cref="NotSameTypePropertyException">
  223. /// </exception>
  224. /// <exception cref="ReadOnlyPropertyException"></exception>
  225. protected void CheckAndConfigureMapping(ref Tuple<Expression, Expression, bool, string> configExpression)
  226. {
  227. Type typeSource = configExpression.Item1.Type;
  228. Type typeTarget = configExpression.Item2.Type;
  229. // 正常情况下,目标表达式是一个成员表达式树
  230. PropertyInfo propTarget = GetPropertyInfo(configExpression.Item2);
  231. if (propTarget.CanWrite)
  232. {
  233. CheckAndRemoveMemberDest(propTarget.Name);
  234. if (!IsListOf(typeTarget))
  235. {
  236. CreatBindingFromSimple(ref configExpression, typeSource, typeTarget, propTarget);
  237. }
  238. else
  239. {
  240. CreateBindingFromList(ref configExpression, typeSource, typeTarget, propTarget);
  241. }
  242. }
  243. else
  244. {
  245. throw new ReadOnlyPropertyException(propTarget);
  246. }
  247. }
  248. /// <summary>
  249. /// 检查并移除目标成员
  250. /// </summary>
  251. /// <param name="properyName">属性名</param>
  252. protected void CheckAndRemoveMemberDest(string properyName)
  253. {
  254. Predicate<MemberAssignment> exp = m => m.Member.Name == properyName;
  255. if (memberForNew.Exists(exp))
  256. {
  257. memberForNew.RemoveAll(exp);
  258. }
  259. }
  260. /// <summary>
  261. /// 获取成员初始化表达式。
  262. /// </summary>
  263. /// <returns></returns>
  264. protected MemberInitExpression GetMemberInitExpression()
  265. {
  266. Type typeDest = GetDestinationType();
  267. NewExpression newClassDest = Expression.New(typeDest);
  268. MemberInitExpression exp = Expression.MemberInit(newClassDest, MemberToMapForNew);
  269. return exp;
  270. }
  271. /// <summary>
  272. /// 创建成员绑定。
  273. /// </summary>
  274. /// <param name="propertyExpression">属性表达式</param>
  275. /// <param name="propertyTarget">目标属性</param>
  276. /// <param name="checkIfNull">是否检查null值</param>
  277. protected void CreateMemberBinding(Expression propertyExpression, MemberInfo propertyTarget, bool checkIfNull)
  278. {
  279. // 访问表达式进行转换
  280. Expression result = visitorMapper.Visit(propertyExpression, checkIfNull);
  281. MemberAssignment bind = Expression.Bind(propertyTarget, result);
  282. memberForNew.Add(bind);
  283. }
  284. /// <summary>
  285. /// 将表达式源的映射分配给属性目标。
  286. /// </summary>
  287. /// <param name="getPropertySource">属性源类型</param>
  288. /// <param name="getPropertyDest">属性目标类型</param>
  289. /// <param name="checkIfNull">是否检查null值</param>
  290. /// <param name="name">要使用的映射器的别名</param>
  291. internal MapperConfigurationBase ForMemberBase(Expression getPropertySource, Expression getPropertyDest, bool checkIfNull, string name = null)
  292. {
  293. // 添加到映射列表并且可以继续操作
  294. PropertiesMapping.Add(Tuple.Create(getPropertySource, getPropertyDest, checkIfNull, name));
  295. return this;
  296. }
  297. /// <summary>
  298. /// 获取属性信息。
  299. /// </summary>
  300. /// <param name="propertyExpression">属性表达式树</param>
  301. /// <returns></returns>
  302. /// <exception cref="System.NotImplementedException">
  303. /// 这种表达方式不承担职责,或者这种类型的表达式是无效的
  304. /// </exception>
  305. protected static PropertyInfo GetPropertyInfo(Expression propertyExpression)
  306. {
  307. var expressionToAnalyse = propertyExpression.NodeType == ExpressionType.Lambda ? (propertyExpression as LambdaExpression).Body : propertyExpression;
  308. switch (expressionToAnalyse.NodeType)
  309. {
  310. case ExpressionType.Convert:
  311. Expression operand = (expressionToAnalyse as UnaryExpression).Operand;
  312. switch (operand.NodeType)
  313. {
  314. case ExpressionType.MemberAccess:
  315. return (operand as MemberExpression).Member as PropertyInfo;
  316. default:
  317. throw new NotImplementedException("这种表达方式目前尚未支持");
  318. }
  319. case ExpressionType.MemberAccess:
  320. return (expressionToAnalyse as MemberExpression).Member as PropertyInfo;
  321. default:
  322. throw new NotImplementedException("这种表达方式目前尚未支持");
  323. }
  324. }
  325. internal void Initialize(Func<Type, object> constructor)
  326. {
  327. CreateMappingExpression(constructor);
  328. CreateMemberAssignementForExistingTarget();
  329. }
  330. public virtual void CreateMemberAssignementForExistingTarget()
  331. {
  332. if (PropertiesMapping.Count > 0)
  333. {
  334. // 用于更改原始表达式的参数。
  335. var paramTarget = Expression.Parameter(TargetType, paramClassSource.Name.Replace("s", "t"));
  336. ChangParameterExpressionVisitor visitSource = new ChangParameterExpressionVisitor(paramClassSource);
  337. ChangParameterExpressionVisitor visitTarget = new ChangParameterExpressionVisitor(paramTarget);
  338. List<Expression> finalAssign = new List<Expression>();
  339. foreach (var item in PropertiesMapping)
  340. {
  341. var propToAssign = visitTarget.Visit(item.Item2);
  342. var assignExpression = visitSource.Visit(item.Item1);
  343. Type sourceType = TypeSystem.GetElementType(item.Item2.Type);
  344. Type targetType = TypeSystem.GetElementType(item.Item1.Type);
  345. if (string.IsNullOrEmpty(item.Item4))
  346. {
  347. object defaultValue = MapperHelper.GetDefaultValue(item.Item2.Type);
  348. Expression defaultExpression = Expression.Constant(defaultValue, item.Item2.Type);
  349. Expression checkIfNull = Expression.NotEqual(assignExpression, defaultExpression);
  350. if (item.Item3)
  351. {
  352. Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
  353. finalAssign.Add(setIf);
  354. }
  355. else
  356. {
  357. if (!IsListOf(propToAssign.Type))
  358. {
  359. finalAssign.Add(Expression.Assign(propToAssign, assignExpression));
  360. }
  361. else
  362. {
  363. if (sourceType == targetType)
  364. {
  365. Expression toListExp = Expression.Call(_toListMethod.MakeGenericMethod(sourceType), assignExpression);
  366. Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
  367. finalAssign.Add(setIf);
  368. }
  369. }
  370. }
  371. }
  372. else // 来自其他映射器。
  373. {
  374. var mapper = GetMapper(sourceType, targetType, false, item.Item4);
  375. if (mapper != null)
  376. {
  377. mapper.Initialize(_constructorFunc);
  378. Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(item.Item2.Type), item.Item2.Type);
  379. if (!IsListOf(propToAssign.Type))
  380. {
  381. ChangParameterExpressionVisitor changeVisitor = new ChangParameterExpressionVisitor(propToAssign, assignExpression);
  382. Expression modifiedExpression = changeVisitor.Visit(mapper.expressionForExisting.Body);
  383. Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression);
  384. Expression setIf = Expression.IfThen(checkIfNull, modifiedExpression);
  385. assignExpression = setIf;
  386. }
  387. else
  388. {
  389. Expression selectExp = Expression.Call(_selectMethod.MakeGenericMethod(sourceType), Expression.Constant(mapper.GetDelegate()));
  390. Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression);
  391. Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
  392. assignExpression = setIf;
  393. }
  394. finalAssign.Add(assignExpression);
  395. }
  396. }
  397. }
  398. if (finalAssign.Count > 0 && _delegateCallForExisting == null)
  399. {
  400. expressionForExisting = Expression.Lambda(Expression.Block(typeof(void), finalAssign), paramClassSource, paramTarget);
  401. // 编译
  402. _delegateCallForExisting = expressionForExisting.Compile();
  403. }
  404. }
  405. }
  406. internal Expression GetLambdaDest(string propertyName)
  407. {
  408. var exp = PropertiesMapping.Find(x => GetPropertyInfo(x.Item1).Name == propertyName);
  409. if (exp != null)
  410. {
  411. var final = exp.Item2;
  412. if (final.NodeType == ExpressionType.Convert)
  413. {
  414. final = (final as UnaryExpression).Operand;
  415. }
  416. return final;
  417. }
  418. return null;
  419. }
  420. public virtual void CreateMappingExpression(Func<Type, object> constructor)
  421. {
  422. if (!_isInitialized)
  423. {
  424. // 它是在处理前放置以避免递归循环。
  425. _isInitialized = true;
  426. _constructorFunc = constructor;
  427. CreateCommonMember();
  428. var propsToAnalyse = PropertiesMapping.ToList(); // 克隆列表以便于更改。
  429. for (int i = 0; i < propsToAnalyse.Count; i++)
  430. {
  431. var propToAnalyse = propsToAnalyse[i];
  432. CheckAndConfigureMapping(ref propToAnalyse);
  433. propsToAnalyse[i] = propToAnalyse;
  434. }
  435. PropertiesMapping = propsToAnalyse;
  436. // 编译
  437. GetDelegate();
  438. }
  439. }
  440. internal Type GetRealType(Type typeToFind)
  441. {
  442. if (UseServiceLocator)
  443. return _constructorFunc(typeToFind).GetType();
  444. return typeToFind;
  445. }
  446. internal PropertiesNotMapped GetPropertiesNotMapped()
  447. {
  448. PropertiesNotMapped result = new PropertiesNotMapped();
  449. // 克隆属性信息
  450. List<PropertyInfo> sourceProperties = SourceType.GetProperties().ToList();
  451. List<PropertyInfo> targetProperties = TargetType.GetProperties().ToList();
  452. PropertiesVisitor visitor = new PropertiesVisitor(TargetType);
  453. foreach (var members in memberForNew)
  454. {
  455. var members1 = members;
  456. sourceProperties.RemoveAll((p) => members1.Member.Name == p.Name);
  457. targetProperties.RemoveAll((p) => visitor.GetProperties(members.Expression).Contains(p));
  458. }
  459. // 检查被忽略映射的成员
  460. sourceProperties.RemoveAll((p) => _propertiesToIgnore.Contains(p));
  461. result.sourceProperties = sourceProperties;
  462. result.targetProperties = targetProperties;
  463. return result;
  464. }
  465. public LambdaExpression GetSortedExpression(string propertySource)
  466. {
  467. Expression result = null;
  468. var exp = PropertiesMapping.Find(x => GetPropertyInfo(x.Item2).Name == propertySource);
  469. if (exp == null)
  470. {
  471. throw new PropertyNoExistException(propertySource, TargetType);
  472. }
  473. // 更改参数
  474. var visitor = new MapperExpressionVisitor(paramClassSource);
  475. result = visitor.Visit(exp.Item1);
  476. return Expression.Lambda(result, paramClassSource);
  477. }
  478. private static bool IsListOf(Type typeTarget)
  479. {
  480. // 特殊情况字符串是char数组。
  481. if (typeTarget == typeof(string))
  482. {
  483. return false;
  484. }
  485. Func<Type, bool> test = t => t.IsAssignableFrom(typeof(IEnumerable));
  486. return test(typeTarget) || typeTarget.GetInterfaces().Any(test);
  487. }
  488. private MapperConfigurationBase GetAndCheckMapper(Type typeOfSource, Type typeOfTarget, string name)
  489. {
  490. var externalMapper = GetMapper(typeOfSource, typeOfTarget, false, name);
  491. if (externalMapper != null)
  492. {
  493. return externalMapper;
  494. }
  495. //如果找不到具有别名的映射器
  496. if (!string.IsNullOrEmpty(name))
  497. {
  498. throw new NoFoundMapperException(name);
  499. }
  500. throw new NotSameTypePropertyException(typeOfSource, typeOfTarget);
  501. }
  502. private void CreatBindingFromSimple(ref Tuple<Expression, Expression, bool, string> configExpression, Type typeSource, Type typeTarget, PropertyInfo propTarget)
  503. {
  504. // 没有特殊的操作
  505. if (typeSource == typeTarget)
  506. {
  507. // 创建成员绑定
  508. CreateMemberBinding(configExpression.Item1, propTarget, configExpression.Item3);
  509. }
  510. else
  511. {
  512. // 尝试查找mapper
  513. MapperConfigurationBase externalMapper = GetAndCheckMapper(typeSource, typeTarget, configExpression.Item4);
  514. // 如果此时未初始化映射器
  515. externalMapper.CreateMappingExpression(_constructorFunc);
  516. // 默认情况下,检查对象的null
  517. Expression mapExpression = externalMapper.GetMemberInitExpression();
  518. Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(configExpression.Item1.Type), configExpression.Item1.Type);
  519. // 修改成员
  520. Expression expSource = visitorMapper.Visit(configExpression.Item1, false);
  521. ChangParameterExpressionVisitor changeParamaterVisitor = new ChangParameterExpressionVisitor(expSource);
  522. mapExpression = changeParamaterVisitor.Visit(mapExpression);
  523. // 现在可以创建正确的参数。
  524. Expression checkIfNull = Expression.NotEqual(expSource, defaultExpression);
  525. // 创建条件
  526. var checkExpression = Expression.Condition(checkIfNull, mapExpression, Expression.Constant(MapperHelper.GetDefaultValue(mapExpression.Type), mapExpression.Type), mapExpression.Type);
  527. MemberAssignment bindExpression = Expression.Bind(propTarget, checkExpression);
  528. // 找到了映射器但没有配置
  529. if (string.IsNullOrEmpty(configExpression.Item4))
  530. {
  531. configExpression = Tuple.Create(configExpression.Item1, configExpression.Item2, configExpression.Item3, externalMapper.Name);
  532. }
  533. memberForNew.Add(bindExpression);
  534. }
  535. }
  536. private void CreateBindingFromList(ref Tuple<Expression, Expression, bool, string> configExpression, Type typeSource, Type typeTarget, PropertyInfo propTarget)
  537. {
  538. Type sourceTypeList = TypeSystem.GetElementType(typeSource);
  539. Type destTypeList = TypeSystem.GetElementType(typeTarget);
  540. if (sourceTypeList == destTypeList)
  541. {
  542. if (configExpression.Item2.NodeType == ExpressionType.MemberAccess)
  543. {
  544. CreateMemberBinding(configExpression.Item1, propTarget, configExpression.Item3);
  545. }
  546. }
  547. // 使用Enumerable类的select方法来更改类型
  548. else
  549. {
  550. var externalMapper = GetAndCheckMapper(sourceTypeList, destTypeList, configExpression.Item4);
  551. externalMapper.CreateMappingExpression(_constructorFunc);
  552. MemberAssignment expBind;
  553. Expression expSource = configExpression.Item1;
  554. ChangParameterExpressionVisitor visitor = new ChangParameterExpressionVisitor(paramClassSource);
  555. expSource = visitor.Visit(expSource);
  556. // 为了与EF / LINQ2SQL兼容。
  557. LambdaExpression expMappeur = externalMapper.GetGenericLambdaExpression();
  558. // 创建对Select方法的调用,在Enumerable的Select中插入一个lambda表达式(参数是一个委托),通常情况下,这是不可能的,但(个人认为)编译器就像这样创建并且LINQ2SQL / EF是可以进行sql查询的
  559. Expression select = Expression.Call(_selectMethod.MakeGenericMethod(sourceTypeList, destTypeList), new Expression[]
  560. {
  561. expSource,
  562. expMappeur
  563. });
  564. // 创建对ToList方法的调用
  565. Expression toList = Expression.Call(_toListMethod.MakeGenericMethod(destTypeList), select);
  566. if (configExpression.Item3) // 如果要检查无效(使用EF / LinqTosql,则不需要)。
  567. {
  568. // 测试source的属性是否为null。
  569. Expression checkIfNull = Expression.NotEqual(expSource, Expression.Constant(MapperHelper.GetDefaultValue(expSource.Type), expSource.Type));
  570. // 有时候ToList方法不起作用,则使用实现ToList不起作用的类
  571. Expression asExp = Expression.TypeAs(toList, propTarget.PropertyType);
  572. // 创建条件表达式
  573. Expression expCondition = Expression.Condition(checkIfNull, asExp, Expression.Constant(MapperHelper.GetDefaultValue(typeTarget), typeTarget));
  574. // 分配给目标属性。
  575. expBind = Expression.Bind(propTarget, expCondition);
  576. }
  577. else
  578. {
  579. // 分配给目标属性。
  580. expBind = Expression.Bind(propTarget, toList);
  581. }
  582. // 查找mapper
  583. if (string.IsNullOrEmpty(configExpression.Item4))
  584. {
  585. configExpression = Tuple.Create(configExpression.Item1, configExpression.Item2, configExpression.Item3, externalMapper.Name);
  586. }
  587. memberForNew.Add(expBind);
  588. }
  589. }
  590. }
  591. }