Hi,
I am trying to deep copy a complex object. Below is code for same.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Reflection;
- namespace DDKOnline.Common
- {
-
-
-
- public static class DeepCopyUtility
- {
-
-
-
-
-
- The source object to copy from
- The target object to copy topublic static void CopyObjectData(object source, object target)
- {
- CopyObjectData(source, target, String.Empty, BindingFlags.Public | BindingFlags.Instance);
- }
-
-
-
-
-
- The source object to copy from
- The target object to copy to
- A comma delimited list of properties that should not be copied
- Reflection binding accesspublic static void CopyObjectData(object source, object target, string excludedProperties, BindingFlags memberAccess)
- {
- string[] excluded = null;
- if (!string.IsNullOrEmpty(excludedProperties))
- {
- excluded = excludedProperties.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
- MemberInfo[] miT = target.GetType().GetMembers(memberAccess);
- foreach (MemberInfo Field in miT)
- {
- string name = Field.Name;
-
- if (string.IsNullOrEmpty(excludedProperties) == false
- && excluded.Contains(name))
- {
- continue;
- }
- if (Field.MemberType == MemberTypes.Field)
- {
- FieldInfo sourcefield = source.GetType().GetField(name);
- if (sourcefield == null) { continue; }
- object SourceValue = sourcefield.GetValue(source);
- ((FieldInfo)Field).SetValue(target, SourceValue);
- }
- else if (Field.MemberType == MemberTypes.Property)
- {
- PropertyInfo piTarget = Field as PropertyInfo;
- PropertyInfo sourceField = source.GetType().GetProperty(name, memberAccess);
- if (sourceField == null) { continue; }
- if (piTarget.CanWrite && sourceField.CanRead)
- {
- object targetValue = piTarget.GetValue(target, null);
- object sourceValue = sourceField.GetValue(source, null);
- if (sourceValue == null) { continue; }
- if (sourceField.PropertyType.IsArray
- && piTarget.PropertyType.IsArray
- && sourceValue != null)
- {
- CopyArray(source, target, memberAccess, piTarget, sourceField, sourceValue);
- }
- else
- {
- CopySingleData(source, target, memberAccess, piTarget, sourceField, targetValue, sourceValue);
- }
- }
- }
- }
- }
- private static void CopySingleData(object source, object target, BindingFlags memberAccess, PropertyInfo piTarget, PropertyInfo sourceField, object targetValue, object sourceValue)
- {
-
- if (targetValue == null
- && piTarget.PropertyType.IsValueType == false
- && piTarget.PropertyType != typeof(string))
- {
- if (piTarget.PropertyType.IsArray)
- {
- targetValue = Activator.CreateInstance(piTarget.PropertyType.GetElementType());
- }
- else
- {
- targetValue = Activator.CreateInstance(piTarget.PropertyType);
- }
- }
- if (piTarget.PropertyType.IsValueType == false
- && piTarget.PropertyType != typeof(string))
- {
- CopyObjectData(sourceValue, targetValue, "", memberAccess);
- piTarget.SetValue(target, targetValue, null);
- }
- else
- {
- if (piTarget.PropertyType.FullName == sourceField.PropertyType.FullName)
- {
- object tempSourceValue = sourceField.GetValue(source, null);
- piTarget.SetValue(target, tempSourceValue, null);
- }
- else
- {
- CopyObjectData(piTarget, target, "", memberAccess);
- }
- }
- }
- private static void CopyArray(object source, object target, BindingFlags memberAccess, PropertyInfo piTarget, PropertyInfo sourceField, object sourceValue)
- {
- int sourceLength = (int)sourceValue.GetType().InvokeMember("Length", BindingFlags.GetProperty, null, sourceValue, null);
- Array targetArray = Array.CreateInstance(piTarget.PropertyType.GetElementType(), sourceLength);
- Array array = (Array)sourceField.GetValue(source, null);
- for (int i = 0; i < array.Length; i++)
- {
- object o = array.GetValue(i);
- object tempTarget = Activator.CreateInstance(piTarget.PropertyType.GetElementType());
- CopyObjectData(o, tempTarget, "", memberAccess);
- targetArray.SetValue(tempTarget, i);
- }
- piTarget.SetValue(target, targetArray, null);
- }
- }
- }
- I want to add list copy also to this code something on below lines.
- if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
- {
- if (typeof(IList).IsAssignableFrom(type))
- {
- var collection = (IList)Activator.CreateInstance(type);
- cloned[source] = collection;
-
- foreach (var element in source as IEnumerable)
- {
- collection.Add(CloneProcedure(element, cloned));
- }
- return collection;
- }
- else if (type.IsGenericType)
- {
- var objectType = type.GetGenericArguments().Single();
- if (typeof(IList<>).MakeGenericType(objectType).IsAssignableFrom(type) ||
- typeof(ISet<>).MakeGenericType(objectType).IsAssignableFrom(type))
- {
- var collection = Activator.CreateInstance(type);
- cloned[source] = collection;
-
- var addMethod = collection.GetType().GetMethod("Add");
- foreach (var element in source as IEnumerable)
- {
- addMethod.Invoke(collection, new[] { CloneProcedure(element, cloned) });
- }
- return collection;
- }
- }
- return source;
- }
But each time I get "Parameter out of bounds" can someone help me with this.
Reference:
https://ddkonline.blogspot.com/2010/04/net-deep-copy-between-2-different.html?_sm_au_=iVV8TZZ5L71MRvZf
https://stackoverflow.com/a/2266441/4583547