Copier.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. return _func.Invoke(source);
  25. }
  26. var memberBindings = new List<MemberBinding>();
  27. foreach (var item in typeof(T).GetProperties())
  28. {
  29. if (DictRule.ContainsKey(item.Name))
  30. {
  31. MemberBinding memberBinding = Expression.Bind(item, DictRule[item.Name]);
  32. memberBindings.Add(memberBinding);
  33. }
  34. else
  35. {
  36. var tInProperty = typeof(T).GetProperty(item.Name);
  37. var tInField = typeof(T).GetField(item.Name);
  38. if (tInProperty != null || tInField != null)
  39. {
  40. MemberExpression property = Expression.PropertyOrField(ParameterExpression, item.Name);
  41. MemberBinding memberBinding = Expression.Bind(item, property);
  42. memberBindings.Add(memberBinding);
  43. }
  44. }
  45. }
  46. foreach (var item in typeof(T).GetFields())
  47. {
  48. if (DictRule.ContainsKey(item.Name))
  49. {
  50. MemberBinding memberBinding = Expression.Bind(item, DictRule[item.Name]);
  51. memberBindings.Add(memberBinding);
  52. }
  53. else
  54. {
  55. var tInProperty = typeof(T).GetProperty(item.Name);
  56. var tInField = typeof(T).GetField(item.Name);
  57. if (tInProperty != null || tInField != null)
  58. {
  59. MemberExpression property = Expression.PropertyOrField(ParameterExpression, item.Name);
  60. MemberBinding memberBinding = Expression.Bind(item, property);
  61. memberBindings.Add(memberBinding);
  62. }
  63. }
  64. }
  65. var memberInitExpression = Expression.MemberInit(Expression.New(typeof(T)), memberBindings.ToArray());
  66. var lambda = Expression.Lambda<Func<T, T>>(memberInitExpression, ParameterExpression);
  67. _func = lambda.Compile();
  68. return _func.Invoke(source);
  69. }
  70. }
  71. }