Copier.cs 3.0 KB

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