MapperConfigurationBase.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  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. /// <summary>
  331. /// 为现有目标对象创建成员
  332. /// </summary>
  333. public virtual void CreateMemberAssignementForExistingTarget()
  334. {
  335. if (PropertiesMapping.Count > 0)
  336. {
  337. // 用于更改原始表达式的参数。
  338. var paramTarget = Expression.Parameter(TargetType, paramClassSource.Name.Replace("s", "t"));
  339. ChangParameterExpressionVisitor visitSource = new ChangParameterExpressionVisitor(paramClassSource);
  340. ChangParameterExpressionVisitor visitTarget = new ChangParameterExpressionVisitor(paramTarget);
  341. List<Expression> finalAssign = new List<Expression>();
  342. foreach (var item in PropertiesMapping)
  343. {
  344. var propToAssign = visitTarget.Visit(item.Item2);
  345. var assignExpression = visitSource.Visit(item.Item1);
  346. Type sourceType = TypeSystem.GetElementType(item.Item2.Type);
  347. Type targetType = TypeSystem.GetElementType(item.Item1.Type);
  348. if (string.IsNullOrEmpty(item.Item4))
  349. {
  350. object defaultValue = MapperHelper.GetDefaultValue(item.Item2.Type);
  351. Expression defaultExpression = Expression.Constant(defaultValue, item.Item2.Type);
  352. Expression checkIfNull = Expression.NotEqual(assignExpression, defaultExpression);
  353. if (item.Item3)
  354. {
  355. Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
  356. finalAssign.Add(setIf);
  357. }
  358. else
  359. {
  360. if (!IsListOf(propToAssign.Type))
  361. {
  362. finalAssign.Add(Expression.Assign(propToAssign, assignExpression));
  363. }
  364. else
  365. {
  366. if (sourceType == targetType)
  367. {
  368. Expression toListExp = Expression.Call(_toListMethod.MakeGenericMethod(sourceType), assignExpression);
  369. Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
  370. finalAssign.Add(setIf);
  371. finalAssign.Add(toListExp);
  372. }
  373. }
  374. }
  375. }
  376. else // 来自其他映射器。
  377. {
  378. var mapper = GetMapper(sourceType, targetType, false, item.Item4);
  379. if (mapper != null)
  380. {
  381. mapper.Initialize(_constructorFunc);
  382. Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(item.Item2.Type), item.Item2.Type);
  383. if (!IsListOf(propToAssign.Type))
  384. {
  385. ChangParameterExpressionVisitor changeVisitor = new ChangParameterExpressionVisitor(propToAssign, assignExpression);
  386. Expression modifiedExpression = changeVisitor.Visit(mapper.expressionForExisting.Body);
  387. Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression);
  388. Expression setIf = Expression.IfThen(checkIfNull, modifiedExpression);
  389. assignExpression = setIf;
  390. }
  391. else
  392. {
  393. //Expression selectExp = Expression.Call(_selectMethod.MakeGenericMethod(sourceType), Expression.Constant(mapper.GetDelegate()));
  394. Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression);
  395. Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
  396. assignExpression = setIf;
  397. }
  398. finalAssign.Add(assignExpression);
  399. }
  400. }
  401. }
  402. if (finalAssign.Count > 0 && _delegateCallForExisting == null)
  403. {
  404. expressionForExisting = Expression.Lambda(Expression.Block(typeof(void), finalAssign), paramClassSource, paramTarget);
  405. // 编译
  406. _delegateCallForExisting = expressionForExisting.Compile();
  407. }
  408. }
  409. }
  410. internal Expression GetLambdaDest(string propertyName)
  411. {
  412. var exp = PropertiesMapping.Find(x => GetPropertyInfo(x.Item1).Name == propertyName);
  413. if (exp != null)
  414. {
  415. var final = exp.Item2;
  416. if (final.NodeType == ExpressionType.Convert)
  417. {
  418. final = (final as UnaryExpression).Operand;
  419. }
  420. return final;
  421. }
  422. return null;
  423. }
  424. /// <summary>
  425. /// 创建映射表达式树
  426. /// </summary>
  427. /// <param name="constructor"></param>
  428. public virtual void CreateMappingExpression(Func<Type, object> constructor)
  429. {
  430. if (!_isInitialized)
  431. {
  432. // 它是在处理前放置以避免递归循环。
  433. _isInitialized = true;
  434. _constructorFunc = constructor;
  435. CreateCommonMember();
  436. var propsToAnalyse = PropertiesMapping.ToList(); // 克隆列表以便于更改。
  437. for (int i = 0; i < propsToAnalyse.Count; i++)
  438. {
  439. var propToAnalyse = propsToAnalyse[i];
  440. CheckAndConfigureMapping(ref propToAnalyse);
  441. propsToAnalyse[i] = propToAnalyse;
  442. }
  443. PropertiesMapping = propsToAnalyse;
  444. // 编译
  445. GetDelegate();
  446. }
  447. }
  448. internal Type GetRealType(Type typeToFind)
  449. {
  450. if (UseServiceLocator)
  451. return _constructorFunc(typeToFind).GetType();
  452. return typeToFind;
  453. }
  454. internal PropertiesNotMapped GetPropertiesNotMapped()
  455. {
  456. PropertiesNotMapped result = new PropertiesNotMapped();
  457. // 克隆属性信息
  458. List<PropertyInfo> sourceProperties = SourceType.GetProperties().ToList();
  459. List<PropertyInfo> targetProperties = TargetType.GetProperties().ToList();
  460. PropertiesVisitor visitor = new PropertiesVisitor(TargetType);
  461. foreach (var members in memberForNew)
  462. {
  463. var members1 = members;
  464. sourceProperties.RemoveAll((p) => members1.Member.Name == p.Name);
  465. targetProperties.RemoveAll((p) => visitor.GetProperties(members.Expression).Contains(p));
  466. }
  467. // 检查被忽略映射的成员
  468. sourceProperties.RemoveAll((p) => _propertiesToIgnore.Contains(p));
  469. result.sourceProperties = sourceProperties;
  470. result.targetProperties = targetProperties;
  471. return result;
  472. }
  473. /// <summary>
  474. /// 获取排序表达式树
  475. /// </summary>
  476. /// <param name="propertySource">属性名</param>
  477. /// <returns></returns>
  478. public LambdaExpression GetSortedExpression(string propertySource)
  479. {
  480. var exp = PropertiesMapping.Find(x => GetPropertyInfo(x.Item2).Name == propertySource);
  481. if (exp == null)
  482. {
  483. throw new PropertyNoExistException(propertySource, TargetType);
  484. }
  485. // 更改参数
  486. var visitor = new MapperExpressionVisitor(paramClassSource);
  487. var result = visitor.Visit(exp.Item1);
  488. return Expression.Lambda(result, paramClassSource);
  489. }
  490. private static bool IsListOf(Type typeTarget)
  491. {
  492. // 特殊情况字符串是char数组。
  493. if (typeTarget == typeof(string))
  494. {
  495. return false;
  496. }
  497. Func<Type, bool> test = t => t.IsAssignableFrom(typeof(IEnumerable));
  498. return test(typeTarget) || typeTarget.GetInterfaces().Any(test);
  499. }
  500. private MapperConfigurationBase GetAndCheckMapper(Type typeOfSource, Type typeOfTarget, string name)
  501. {
  502. var externalMapper = GetMapper(typeOfSource, typeOfTarget, false, name);
  503. if (externalMapper != null)
  504. {
  505. return externalMapper;
  506. }
  507. //如果找不到具有别名的映射器
  508. if (!string.IsNullOrEmpty(name))
  509. {
  510. throw new NoFoundMapperException(name);
  511. }
  512. throw new NotSameTypePropertyException(typeOfSource, typeOfTarget);
  513. }
  514. private void CreatBindingFromSimple(ref Tuple<Expression, Expression, bool, string> configExpression, Type typeSource, Type typeTarget, PropertyInfo propTarget)
  515. {
  516. // 没有特殊的操作
  517. if (typeSource == typeTarget)
  518. {
  519. // 创建成员绑定
  520. CreateMemberBinding(configExpression.Item1, propTarget, configExpression.Item3);
  521. }
  522. else
  523. {
  524. // 尝试查找mapper
  525. MapperConfigurationBase externalMapper = GetAndCheckMapper(typeSource, typeTarget, configExpression.Item4);
  526. // 如果此时未初始化映射器
  527. externalMapper.CreateMappingExpression(_constructorFunc);
  528. // 默认情况下,检查对象的null
  529. Expression mapExpression = externalMapper.GetMemberInitExpression();
  530. Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(configExpression.Item1.Type), configExpression.Item1.Type);
  531. // 修改成员
  532. Expression expSource = visitorMapper.Visit(configExpression.Item1);
  533. ChangParameterExpressionVisitor changeParamaterVisitor = new ChangParameterExpressionVisitor(expSource);
  534. mapExpression = changeParamaterVisitor.Visit(mapExpression);
  535. // 现在可以创建正确的参数。
  536. Expression checkIfNull = Expression.NotEqual(expSource, defaultExpression);
  537. // 创建条件
  538. var checkExpression = Expression.Condition(checkIfNull, mapExpression, Expression.Constant(MapperHelper.GetDefaultValue(mapExpression.Type), mapExpression.Type), mapExpression.Type);
  539. MemberAssignment bindExpression = Expression.Bind(propTarget, checkExpression);
  540. // 找到了映射器但没有配置
  541. if (string.IsNullOrEmpty(configExpression.Item4))
  542. {
  543. configExpression = Tuple.Create(configExpression.Item1, configExpression.Item2, configExpression.Item3, externalMapper.Name);
  544. }
  545. memberForNew.Add(bindExpression);
  546. }
  547. }
  548. private void CreateBindingFromList(ref Tuple<Expression, Expression, bool, string> configExpression, Type typeSource, Type typeTarget, PropertyInfo propTarget)
  549. {
  550. Type sourceTypeList = TypeSystem.GetElementType(typeSource);
  551. Type destTypeList = TypeSystem.GetElementType(typeTarget);
  552. if (sourceTypeList == destTypeList)
  553. {
  554. if (configExpression.Item2.NodeType == ExpressionType.MemberAccess)
  555. {
  556. CreateMemberBinding(configExpression.Item1, propTarget, configExpression.Item3);
  557. }
  558. }
  559. // 使用Enumerable类的select方法来更改类型
  560. else
  561. {
  562. var externalMapper = GetAndCheckMapper(sourceTypeList, destTypeList, configExpression.Item4);
  563. externalMapper.CreateMappingExpression(_constructorFunc);
  564. MemberAssignment expBind;
  565. Expression expSource = configExpression.Item1;
  566. ChangParameterExpressionVisitor visitor = new ChangParameterExpressionVisitor(paramClassSource);
  567. expSource = visitor.Visit(expSource);
  568. // 为了与EF / LINQ2SQL兼容。
  569. LambdaExpression expMappeur = externalMapper.GetGenericLambdaExpression();
  570. // 创建对Select方法的调用,在Enumerable的Select中插入一个lambda表达式(参数是一个委托),通常情况下,这是不可能的,但(个人认为)编译器就像这样创建并且LINQ2SQL / EF是可以进行sql查询的
  571. Expression select = Expression.Call(_selectMethod.MakeGenericMethod(sourceTypeList, destTypeList), new[]
  572. {
  573. expSource,
  574. expMappeur
  575. });
  576. // 创建对ToList方法的调用
  577. Expression toList = Expression.Call(_toListMethod.MakeGenericMethod(destTypeList), select);
  578. if (configExpression.Item3) // 如果要检查无效(使用EF / LinqTosql,则不需要)。
  579. {
  580. // 测试source的属性是否为null。
  581. Expression checkIfNull = Expression.NotEqual(expSource, Expression.Constant(MapperHelper.GetDefaultValue(expSource.Type), expSource.Type));
  582. // 有时候ToList方法不起作用,则使用实现ToList不起作用的类
  583. Expression asExp = Expression.TypeAs(toList, propTarget.PropertyType);
  584. // 创建条件表达式
  585. Expression expCondition = Expression.Condition(checkIfNull, asExp, Expression.Constant(MapperHelper.GetDefaultValue(typeTarget), typeTarget));
  586. // 分配给目标属性。
  587. expBind = Expression.Bind(propTarget, expCondition);
  588. }
  589. else
  590. {
  591. // 分配给目标属性。
  592. expBind = Expression.Bind(propTarget, toList);
  593. }
  594. // 查找mapper
  595. if (string.IsNullOrEmpty(configExpression.Item4))
  596. {
  597. configExpression = Tuple.Create(configExpression.Item1, configExpression.Item2, configExpression.Item3, externalMapper.Name);
  598. }
  599. memberForNew.Add(expBind);
  600. }
  601. }
  602. }
  603. }