CloneHelper.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using DevExpress.Xpo;
  2. using DevExpress.Xpo.Metadata;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace Ips.Library.DxpLib
  9. {
  10. public class CloneHelper : IDisposable
  11. {
  12. readonly Dictionary<object, object> clonedObjects;
  13. readonly Session targetSession;
  14. public CloneHelper(Session targetSession)
  15. {
  16. clonedObjects = new Dictionary<object, object>();
  17. this.targetSession = targetSession;
  18. }
  19. public T Clone<T>(T source)
  20. {
  21. return Clone<T>(source, false);
  22. }
  23. public T Clone<T>(T source, bool synchronize)
  24. {
  25. return (T)Clone((object)source, synchronize);
  26. }
  27. public object Clone(object source)
  28. {
  29. return Clone(source, false);
  30. }
  31. public object Clone(object source, bool synchronize)
  32. {
  33. if (source == null)
  34. return null;
  35. XPClassInfo targetClassInfo = targetSession.GetClassInfo(source.GetType());
  36. object target = targetClassInfo.CreateNewObject(targetSession);
  37. clonedObjects.Add(source, target);
  38. foreach (XPMemberInfo m in targetClassInfo.PersistentProperties)
  39. {
  40. CloneProperty(m, source, target, synchronize);
  41. }
  42. foreach (XPMemberInfo m in targetClassInfo.CollectionProperties)
  43. {
  44. CloneCollection(m, source, target, synchronize);
  45. }
  46. return target;
  47. }
  48. private void CloneProperty(XPMemberInfo memberInfo, object source, object target, bool synchronize)
  49. {
  50. if (memberInfo is DevExpress.Xpo.Metadata.Helpers.ServiceField || memberInfo.IsKey)
  51. {
  52. return;
  53. }
  54. object clonedValue = null;
  55. if (memberInfo.ReferenceType != null)
  56. {
  57. object value = memberInfo.GetValue(source);
  58. if (value != null)
  59. {
  60. clonedValue = CloneValue(value, synchronize, false);
  61. }
  62. }
  63. else
  64. {
  65. clonedValue = memberInfo.GetValue(source);
  66. }
  67. memberInfo.SetValue(target, clonedValue);
  68. }
  69. private void CloneCollection(XPMemberInfo memberInfo, object source, object target, bool synchronize)
  70. {
  71. if (memberInfo.IsAssociation && (memberInfo.IsManyToMany || memberInfo.IsAggregated))
  72. {
  73. XPBaseCollection colTarget = (XPBaseCollection)memberInfo.GetValue(target);
  74. XPBaseCollection colSource = (XPBaseCollection)memberInfo.GetValue(source);
  75. foreach (IXPSimpleObject obj in colSource)
  76. {
  77. colTarget.BaseAdd(CloneValue(obj, synchronize, !memberInfo.IsManyToMany));
  78. }
  79. }
  80. }
  81. private object CloneValue(object propertyValue, bool synchronize, bool cloneAlways)
  82. {
  83. if (clonedObjects.ContainsKey(propertyValue))
  84. {
  85. return clonedObjects[propertyValue];
  86. }
  87. object clonedValue = null;
  88. if (synchronize && !cloneAlways)
  89. {
  90. clonedValue = targetSession.GetObjectByKey(targetSession.GetClassInfo(propertyValue), targetSession.GetKeyValue(propertyValue));
  91. }
  92. if (clonedValue == null)
  93. {
  94. clonedValue = Clone(propertyValue, synchronize);
  95. }
  96. return clonedValue;
  97. }
  98. public void Dispose()
  99. {
  100. if (targetSession != null)
  101. targetSession.Dispose();
  102. }
  103. }
  104. }