Copier.cs 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq.Expressions;
  4. namespace Masuit.Tools.Mapping
  5. {
  6. /// <summary>
  7. /// 表达式树复制对象
  8. /// </summary>
  9. /// <typeparam name="T"></typeparam>
  10. public static class Copier<T>
  11. {
  12. private static readonly ParameterExpression ParameterExpression = Expression.Parameter(typeof(T), "p");
  13. private static Func<T, T> _func;
  14. private static readonly Dictionary<string, Expression> DictRule = new Dictionary<string, Expression>();
  15. /// <summary>
  16. /// 深拷贝
  17. /// </summary>
  18. /// <param name="source"></param>
  19. /// <returns></returns>
  20. public static T Copy(T source)
  21. {
  22. if (_func == null)
  23. {
  24. List<MemberBinding> memberBindings = new List<MemberBinding>();
  25. foreach (var item in typeof(T).GetProperties())
  26. {
  27. if (DictRule.ContainsKey(item.Name))
  28. {
  29. MemberBinding memberBinding = Expression.Bind(item, DictRule[item.Name]);
  30. memberBindings.Add(memberBinding);
  31. }
  32. else
  33. {
  34. var tInProperty = typeof(T).GetProperty(item.Name);
  35. var tInField = typeof(T).GetField(item.Name);
  36. if (tInProperty != null || tInField != null)
  37. {
  38. MemberExpression property = Expression.PropertyOrField(ParameterExpression, item.Name);
  39. MemberBinding memberBinding = Expression.Bind(item, property);
  40. memberBindings.Add(memberBinding);
  41. }
  42. }
  43. }
  44. foreach (var item in typeof(T).GetFields())
  45. {
  46. if (DictRule.ContainsKey(item.Name))
  47. {
  48. MemberBinding memberBinding = Expression.Bind(item, DictRule[item.Name]);
  49. memberBindings.Add(memberBinding);
  50. }
  51. else
  52. {
  53. var tInProperty = typeof(T).GetProperty(item.Name);
  54. var tInField = typeof(T).GetField(item.Name);
  55. if (tInProperty != null || tInField != null)
  56. {
  57. MemberExpression property = Expression.PropertyOrField(ParameterExpression, item.Name);
  58. MemberBinding memberBinding = Expression.Bind(item, property);
  59. memberBindings.Add(memberBinding);
  60. }
  61. }
  62. }
  63. MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(T)), memberBindings.ToArray());
  64. Expression<Func<T, T>> lambda = Expression.Lambda<Func<T, T>>(memberInitExpression, ParameterExpression);
  65. _func = lambda.Compile();
  66. }
  67. return _func.Invoke(source);
  68. }
  69. }
  70. }