PropertyUtil.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. using CyberX8_Core;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Linq;
  7. using System.Reflection;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. namespace MECF.Framework.Common.Utilities
  11. {
  12. public class PropertyUtil
  13. {
  14. public static object Clone(object source)
  15. {
  16. Type type = source.GetType();
  17. object target = System.Activator.CreateInstance(type);
  18. BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;
  19. PropertyInfo[] propertyInfos = type.GetProperties(bindingFlags);
  20. foreach (PropertyInfo property in propertyInfos)
  21. {
  22. if (!property.CanWrite) continue;
  23. //check whether property type is value type, enum or string type
  24. if (property.PropertyType.IsPrimitive || property.PropertyType.IsEnum || property.PropertyType == typeof(string))
  25. {
  26. property.SetValue(target, property.GetValue(source, null), null);
  27. }
  28. else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
  29. {
  30. //Include List and Dictionary and......
  31. if (property.PropertyType.IsGenericType)
  32. {
  33. var cloneObj = Activator.CreateInstance(property.PropertyType);
  34. var addMethod = property.PropertyType.GetMethod("Add", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  35. Debug.Assert(null != addMethod);
  36. var currentValues = property.GetValue(source, null) as IEnumerable;
  37. if (currentValues == null)
  38. {
  39. property.SetValue(target, null, null);
  40. }
  41. else
  42. {
  43. if (cloneObj is IDictionary)
  44. {
  45. cloneObj = cloneObj as IDictionary;
  46. foreach (var currentValue in currentValues)
  47. {
  48. var propInfoKey = currentValue.GetType().GetProperty("Key");
  49. var propInfoValue = currentValue.GetType().GetProperty("Value");
  50. if (propInfoKey != null && propInfoValue != null)
  51. {
  52. var keyValue = propInfoKey.GetValue(currentValue, null);
  53. var valueValue = propInfoValue.GetValue(currentValue, null);
  54. object finalKeyValue, finalValueValue;
  55. //Get finalKeyValue
  56. var currentKeyType = keyValue.GetType();
  57. if (currentKeyType.IsPrimitive || currentKeyType.IsEnum || currentKeyType == typeof(string))
  58. {
  59. finalKeyValue = keyValue;
  60. }
  61. else
  62. {
  63. //Reference type
  64. var copyObj = Clone(keyValue);
  65. finalKeyValue = copyObj;
  66. }
  67. //Get finalValueValue
  68. var currentValueType = valueValue.GetType();
  69. if (currentValueType.IsPrimitive || currentValueType.IsEnum || currentValueType == typeof(string))
  70. {
  71. finalValueValue = valueValue;
  72. }
  73. else
  74. {
  75. //Reference type
  76. var copyObj = Clone(valueValue);
  77. finalValueValue = copyObj;
  78. }
  79. addMethod.Invoke(cloneObj, new[] { finalKeyValue, finalValueValue });
  80. }
  81. }
  82. property.SetValue(target, cloneObj, null);
  83. }
  84. //Common IList type
  85. else
  86. {
  87. foreach (var currentValue in currentValues)
  88. {
  89. var currentType = currentValue.GetType();
  90. if (currentType.IsPrimitive || currentType.IsEnum || currentType == typeof(string))
  91. {
  92. addMethod.Invoke(cloneObj, new[] { currentValue });
  93. }
  94. else
  95. {
  96. //Reference type
  97. var copyObj = Clone(currentValue);
  98. addMethod.Invoke(cloneObj, new[] { copyObj });
  99. }
  100. }
  101. property.SetValue(target, cloneObj, null);
  102. }
  103. }
  104. }
  105. //Array type
  106. else
  107. {
  108. var currentValues = property.GetValue(source, null) as Array;
  109. if (null == currentValues)
  110. {
  111. property.SetValue(target, null, null);
  112. }
  113. else
  114. {
  115. var cloneObj = Activator.CreateInstance(property.PropertyType, currentValues.Length) as Array;
  116. var arrayList = new ArrayList();
  117. for (var i = 0; i < currentValues.Length; i++)
  118. {
  119. var currentType = currentValues.GetValue(i).GetType();
  120. if (currentType.IsPrimitive || currentType.IsEnum || currentType == typeof(string))
  121. {
  122. arrayList.Add(currentValues.GetValue(i));
  123. }
  124. else
  125. {
  126. //Reference type
  127. var copyObj = Clone(currentValues.GetValue(i));
  128. arrayList.Add(copyObj);
  129. }
  130. }
  131. arrayList.CopyTo(cloneObj, 0);
  132. property.SetValue(target, cloneObj, null);
  133. }
  134. }
  135. }
  136. else if (property.PropertyType.IsClass)
  137. {
  138. object inner = property.GetValue(source, null);
  139. property.SetValue(target, Clone(inner), null);
  140. }
  141. else
  142. {
  143. property.SetValue(target, property.GetValue(source, null), null);
  144. }
  145. }
  146. return target;
  147. }
  148. }
  149. }