using CyberX8_Core; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace MECF.Framework.Common.Utilities { public class PropertyUtil { public static object Clone(object source) { Type type = source.GetType(); object target = System.Activator.CreateInstance(type); BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; PropertyInfo[] propertyInfos = type.GetProperties(bindingFlags); foreach (PropertyInfo property in propertyInfos) { if (!property.CanWrite) continue; //check whether property type is value type, enum or string type if (property.PropertyType.IsPrimitive || property.PropertyType.IsEnum || property.PropertyType == typeof(string)) { property.SetValue(target, property.GetValue(source, null), null); } else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType)) { //Include List and Dictionary and...... if (property.PropertyType.IsGenericType) { var cloneObj = Activator.CreateInstance(property.PropertyType); var addMethod = property.PropertyType.GetMethod("Add", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); Debug.Assert(null != addMethod); var currentValues = property.GetValue(source, null) as IEnumerable; if (currentValues == null) { property.SetValue(target, null, null); } else { if (cloneObj is IDictionary) { cloneObj = cloneObj as IDictionary; foreach (var currentValue in currentValues) { var propInfoKey = currentValue.GetType().GetProperty("Key"); var propInfoValue = currentValue.GetType().GetProperty("Value"); if (propInfoKey != null && propInfoValue != null) { var keyValue = propInfoKey.GetValue(currentValue, null); var valueValue = propInfoValue.GetValue(currentValue, null); object finalKeyValue, finalValueValue; //Get finalKeyValue var currentKeyType = keyValue.GetType(); if (currentKeyType.IsPrimitive || currentKeyType.IsEnum || currentKeyType == typeof(string)) { finalKeyValue = keyValue; } else { //Reference type var copyObj = Clone(keyValue); finalKeyValue = copyObj; } //Get finalValueValue var currentValueType = valueValue.GetType(); if (currentValueType.IsPrimitive || currentValueType.IsEnum || currentValueType == typeof(string)) { finalValueValue = valueValue; } else { //Reference type var copyObj = Clone(valueValue); finalValueValue = copyObj; } addMethod.Invoke(cloneObj, new[] { finalKeyValue, finalValueValue }); } } property.SetValue(target, cloneObj, null); } //Common IList type else { foreach (var currentValue in currentValues) { var currentType = currentValue.GetType(); if (currentType.IsPrimitive || currentType.IsEnum || currentType == typeof(string)) { addMethod.Invoke(cloneObj, new[] { currentValue }); } else { //Reference type var copyObj = Clone(currentValue); addMethod.Invoke(cloneObj, new[] { copyObj }); } } property.SetValue(target, cloneObj, null); } } } //Array type else { var currentValues = property.GetValue(source, null) as Array; if (null == currentValues) { property.SetValue(target, null, null); } else { var cloneObj = Activator.CreateInstance(property.PropertyType, currentValues.Length) as Array; var arrayList = new ArrayList(); for (var i = 0; i < currentValues.Length; i++) { var currentType = currentValues.GetValue(i).GetType(); if (currentType.IsPrimitive || currentType.IsEnum || currentType == typeof(string)) { arrayList.Add(currentValues.GetValue(i)); } else { //Reference type var copyObj = Clone(currentValues.GetValue(i)); arrayList.Add(copyObj); } } arrayList.CopyTo(cloneObj, 0); property.SetValue(target, cloneObj, null); } } } else if (property.PropertyType.IsClass) { object inner = property.GetValue(source, null); property.SetValue(target, Clone(inner), null); } else { property.SetValue(target, property.GetValue(source, null), null); } } return target; } } }