TECHNOLOGIES
FORUMS
JOBS
BOOKS
EVENTS
INTERVIEWS
Live
MORE
LEARN
Training
CAREER
MEMBERS
VIDEOS
NEWS
BLOGS
Sign Up
Login
No unread comment.
View All Comments
No unread message.
View All Messages
No unread notification.
View All Notifications
Answers
Post
An Article
A Blog
A News
A Video
An EBook
An Interview Question
Ask Question
Forums
Monthly Leaders
Forum guidelines
Kavya Shetty
NA
2
6.4k
Deep Copy a complex object in C#
Nov 17 2017 4:31 AM
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
{
/// <summary>
/// Utility
/// </summary>
public
static
class
DeepCopyUtility
{
/// <summary>
/// Copies the data of one object to another. The target object gets properties of the first.
/// Any matching properties (by name) are written to the target.
/// </summary>
///
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);
}
/// <summary>
/// Copies the data of one object to another. The target object gets properties of the first.
/// Any matching properties (by name) are written to the target.
/// </summary>
///
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;
// Skip over excluded properties
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)
{
//instantiate target if needed
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
Reply
Answers (
1
)
How to click link in html table and use the id in that row
Table not displaying properly when using Datatable pluging