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 sealed class CloneUtil { public static bool CheckIsChanged(T OldValue, T NewValue) { Type typeSource = OldValue.GetType(); PropertyInfo[] propertyInfo = typeSource.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); Type typeNewSource = NewValue.GetType(); PropertyInfo[] newPropertyInfo = typeNewSource.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (PropertyInfo property in propertyInfo) { //Check whether property can be written to if (!property.CanWrite) continue; if (property.Name == "IsNotifying") continue; //check whether property type is value type, enum or string type if (property.PropertyType.IsPrimitive || property.PropertyType.IsEnum) { var newProperty = newPropertyInfo.Where(x => x.Name == property.Name).FirstOrDefault(); if (property.GetValue(OldValue, null) != newProperty.GetValue(NewValue, null)) { return false; } } else if (property.PropertyType == typeof(string)) { var oldPropertyValue = property.GetValue(OldValue, null) == null ? "" : property.GetValue(OldValue, null); var newProperty = newPropertyInfo.Where(x => x.Name == property.Name).FirstOrDefault(); var newPropertyValue = newProperty.GetValue(NewValue, null) == null ? "" : newProperty.GetValue(NewValue, null); if (oldPropertyValue != newPropertyValue) { return false; } } } return true; } public static object CloneObject(object objSource) { //Get the type of source object and create a new instance of that type Type typeSource = objSource.GetType(); object objTarget = Activator.CreateInstance(typeSource); //Get all the properties of source object type PropertyInfo[] propertyInfo = typeSource.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); //Assign all source property to taget object 's properties foreach (PropertyInfo property in propertyInfo) { //Check whether property can be written to if (!property.CanWrite) continue; if (property.Name == "StepNo") 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(objTarget, property.GetValue(objSource, 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(objSource, null) as IEnumerable; if (currentValues == null) { property.SetValue(objTarget, 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 = CloneObject(keyValue); finalKeyValue = copyObj; } //Get finalValueValue var currentValueType = valueValue.GetType(); if (currentValueType.IsPrimitive || currentValueType.IsEnum || currentValueType == typeof(string)) { finalValueValue = valueValue; } else { //Reference type var copyObj = CloneObject(valueValue); finalValueValue = copyObj; } addMethod.Invoke(cloneObj, new[] { finalKeyValue, finalValueValue }); } } property.SetValue(objTarget, 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 = CloneObject(currentValue); addMethod.Invoke(cloneObj, new[] { copyObj }); } } property.SetValue(objTarget, cloneObj, null); } } } //Array type else { var currentValues = property.GetValue(objSource, null) as Array; if (null == currentValues) { property.SetValue(objTarget, 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 = CloneObject(currentValues.GetValue(i)); arrayList.Add(copyObj); } } arrayList.CopyTo(cloneObj, 0); property.SetValue(objTarget, cloneObj, null); } } } //else property type is object/complex types, so need to recursively call this method until the end of the tree is reached else { object objPropertyValue = property.GetValue(objSource, null); if (objPropertyValue == null) { property.SetValue(objTarget, null, null); } else if (objPropertyValue.GetType().IsPrimitive || objPropertyValue.GetType().IsEnum || objPropertyValue.GetType() == typeof(string)) { property.SetValue(objTarget, objPropertyValue, null); } else { property.SetValue(objTarget, CloneObject(objPropertyValue), null); } } } return objTarget; } public static object CloneObjectSetFlag(object objSource, string flag, bool setValue) { //Get the type of source object and create a new instance of that type Type typeSource = objSource.GetType(); object objTarget = Activator.CreateInstance(typeSource); //Get all the properties of source object type PropertyInfo[] propertyInfo = typeSource.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); //Assign all source property to taget object 's properties foreach (PropertyInfo property in propertyInfo) { //Check whether property can be written to if (!property.CanWrite) continue; if (property.Name == "StepNo") continue; //check whether property type is value type, enum or string type if (property.PropertyType.IsPrimitive || property.PropertyType.IsEnum || property.PropertyType == typeof(string)) { if (property.Name.Contains(flag)) { } else { property.SetValue(objTarget, property.GetValue(objSource, 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(objSource, null) as IEnumerable; if (currentValues == null) { property.SetValue(objTarget, 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 = CloneObjectSetFlag(keyValue, flag, setValue); finalKeyValue = copyObj; } //Get finalValueValue var currentValueType = valueValue.GetType(); if (currentValueType.IsPrimitive || currentValueType.IsEnum || currentValueType == typeof(string)) { finalValueValue = valueValue; } else { //Reference type var copyObj = CloneObjectSetFlag(valueValue, flag, setValue); finalValueValue = copyObj; } addMethod.Invoke(cloneObj, new[] { finalKeyValue, finalValueValue }); } } property.SetValue(objTarget, 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 = CloneObjectSetFlag(currentValue, flag, setValue); addMethod.Invoke(cloneObj, new[] { copyObj }); } } property.SetValue(objTarget, cloneObj, null); } } } //Array type else { var currentValues = property.GetValue(objSource, null) as Array; if (null == currentValues) { property.SetValue(objTarget, 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 = CloneObjectSetFlag(currentValues.GetValue(i), flag, setValue); arrayList.Add(copyObj); } } arrayList.CopyTo(cloneObj, 0); property.SetValue(objTarget, cloneObj, null); } } } //else property type is object/complex types, so need to recursively call this method until the end of the tree is reached else { object objPropertyValue = property.GetValue(objSource, null); if (objPropertyValue == null) { property.SetValue(objTarget, null, null); } else if (objPropertyValue.GetType().IsPrimitive || objPropertyValue.GetType().IsEnum || objPropertyValue.GetType() == typeof(string)) { property.SetValue(objTarget, objPropertyValue, null); } else { property.SetValue(objTarget, CloneObjectSetFlag(objPropertyValue, flag, setValue), null); } } } return objTarget; } public static object CloneAllObject(object objSource) { //Get the type of source object and create a new instance of that type Type typeSource = objSource.GetType(); object objTarget = Activator.CreateInstance(typeSource); //Get all the properties of source object type PropertyInfo[] propertyInfo = typeSource.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); //Assign all source property to taget object 's properties foreach (PropertyInfo property in propertyInfo) { //Check whether property can be written to 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(objTarget, property.GetValue(objSource, 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(objSource, null) as IEnumerable; if (currentValues == null) { property.SetValue(objTarget, 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 = CloneObject(keyValue); finalKeyValue = copyObj; } //Get finalValueValue var currentValueType = valueValue.GetType(); if (currentValueType.IsPrimitive || currentValueType.IsEnum || currentValueType == typeof(string)) { finalValueValue = valueValue; } else { //Reference type var copyObj = CloneObject(valueValue); finalValueValue = copyObj; } addMethod.Invoke(cloneObj, new[] { finalKeyValue, finalValueValue }); } } property.SetValue(objTarget, 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 = CloneObject(currentValue); addMethod.Invoke(cloneObj, new[] { copyObj }); } } property.SetValue(objTarget, cloneObj, null); } } } //Array type else { var currentValues = property.GetValue(objSource, null) as Array; if (null == currentValues) { property.SetValue(objTarget, 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 = CloneObject(currentValues.GetValue(i)); arrayList.Add(copyObj); } } arrayList.CopyTo(cloneObj, 0); property.SetValue(objTarget, cloneObj, null); } } } //else property type is object/complex types, so need to recursively call this method until the end of the tree is reached else { object objPropertyValue = property.GetValue(objSource, null); if (objPropertyValue == null) { property.SetValue(objTarget, null, null); } else if (objPropertyValue.GetType().IsPrimitive || objPropertyValue.GetType().IsEnum || objPropertyValue.GetType() == typeof(string)) { property.SetValue(objTarget, objPropertyValue, null); } else { property.SetValue(objTarget, CloneObject(objPropertyValue), null); } } } return objTarget; } } }