/*
Hi guys, has anyone come across any scenario wherein you needed to merge one object with another object of same type, merging the complete object graph.
for e.g. If i have a person object and one person object is having first name and other the last name, some way to merge both the objects into a single object.
*/
public class Person
{
public Int32 Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class MyClass
{
//both instances refer to the same person, probably coming from different sources
Person obj1 = new Person(); obj1.Id=1; obj1.FirstName = "Tiju";
Person obj2 = new Person(); ojb2.Id=1; obj2.LastName = "John";
//some way of merging both the object
obj1.MergeObject(obj2); //??
//obj1.Id // = 1
//obj1.FirstName // = "Tiju"
//obj1.LastName // = "John"
}
/*
I had come across such type of requirement and I wrote an extension method to do the same.
*/
public static class ExtensionMethods
{
private const string Key = "Id";
public static IList MergeList(this IList source, IList target)
{
Dictionary itemData = new Dictionary();
//fill the dictionary for existing list
string temp = null;
foreach (object item in source)
{
temp = GetKeyOfRecord(item);
if (!String.IsNullOrEmpty(temp))
itemData[temp] = item;
}
//if the same id exists, merge the object, otherwise add to the existing list.
foreach (object item in target)
{
temp = GetKeyOfRecord(item);
if (!String.IsNullOrEmpty(temp) && itemData.ContainsKey(temp))
itemData[temp].MergeObject(item);
else
source.Add(item);
}
return source;
}
private static string GetKeyOfRecord(object o)
{
string keyValue = null;
Type pointType = o.GetType();
if (pointType != null)
foreach (PropertyInfo propertyItem in pointType.GetProperties())
{
if (propertyItem.Name == Key)
{ keyValue = (string)propertyItem.GetValue(o, null); }
}
return keyValue;
}
public static object MergeObject(this object source, object target)
{
if (source != null && target != null)
{
Type typeSource = source.GetType();
Type typeTarget = target.GetType();
//if both types are same, try to merge
if (typeSource != null && typeTarget != null && typeSource.FullName == typeTarget.FullName)
if (typeSource.IsClass && !typeSource.Namespace.Equals("System", StringComparison.InvariantCulture))
{
PropertyInfo[] propertyList = typeSource.GetProperties();
for (int index = 0; index < propertyList.Length; index++)
{
Type tempPropertySourceValueType = null;
object tempPropertySourceValue = null;
Type tempPropertyTargetValueType = null;
object tempPropertyTargetValue = null;
//get rid of indexers
if (propertyList[index].GetIndexParameters().Length == 0)
{
tempPropertySourceValue = propertyList[index].GetValue(source, null);
tempPropertyTargetValue = propertyList[index].GetValue(target, null);
}
if (tempPropertySourceValue != null)
tempPropertySourceValueType = tempPropertySourceValue.GetType();
if (tempPropertyTargetValue != null)
tempPropertyTargetValueType = tempPropertyTargetValue.GetType();
//if the property is a list
IList ilistSource = tempPropertySourceValue as IList;
IList ilistTarget = tempPropertyTargetValue as IList;
if (ilistSource != null || ilistTarget != null)
{
if (ilistSource != null)
ilistSource.MergeList(ilistTarget);
else
propertyList[index].SetValue(source, ilistTarget, null);
}
//if the property is a Dto
else if (tempPropertySourceValue != null || tempPropertyTargetValue != null)
{
if (tempPropertySourceValue != null)
tempPropertySourceValue.MergeObject(tempPropertyTargetValue);
else
propertyList[index].SetValue(source, tempPropertyTargetValue, null);
}
}
}
}
return source;
}
}
/*
However, this works when the source property is null, if target has it, it will copy that to source.
IT can still be improved to merge when inconsistencies are there e.g. if FirstName="Tiju" and FirstName="John"
Any commments appreciated.
Thanks
TJ
*/
tijujohn83
None
0 Points
4 Posts
Merging Object graph
Jun 16, 2010 09:03 AM|LINK
/* Hi guys, has anyone come across any scenario wherein you needed to merge one object with another object of same type, merging the complete object graph. for e.g. If i have a person object and one person object is having first name and other the last name, some way to merge both the objects into a single object. */ public class Person { public Int32 Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } public class MyClass { //both instances refer to the same person, probably coming from different sources Person obj1 = new Person(); obj1.Id=1; obj1.FirstName = "Tiju"; Person obj2 = new Person(); ojb2.Id=1; obj2.LastName = "John"; //some way of merging both the object obj1.MergeObject(obj2); //?? //obj1.Id // = 1 //obj1.FirstName // = "Tiju" //obj1.LastName // = "John" } /* I had come across such type of requirement and I wrote an extension method to do the same. */ public static class ExtensionMethods { private const string Key = "Id"; public static IList MergeList(this IList source, IList target) { Dictionary itemData = new Dictionary(); //fill the dictionary for existing list string temp = null; foreach (object item in source) { temp = GetKeyOfRecord(item); if (!String.IsNullOrEmpty(temp)) itemData[temp] = item; } //if the same id exists, merge the object, otherwise add to the existing list. foreach (object item in target) { temp = GetKeyOfRecord(item); if (!String.IsNullOrEmpty(temp) && itemData.ContainsKey(temp)) itemData[temp].MergeObject(item); else source.Add(item); } return source; } private static string GetKeyOfRecord(object o) { string keyValue = null; Type pointType = o.GetType(); if (pointType != null) foreach (PropertyInfo propertyItem in pointType.GetProperties()) { if (propertyItem.Name == Key) { keyValue = (string)propertyItem.GetValue(o, null); } } return keyValue; } public static object MergeObject(this object source, object target) { if (source != null && target != null) { Type typeSource = source.GetType(); Type typeTarget = target.GetType(); //if both types are same, try to merge if (typeSource != null && typeTarget != null && typeSource.FullName == typeTarget.FullName) if (typeSource.IsClass && !typeSource.Namespace.Equals("System", StringComparison.InvariantCulture)) { PropertyInfo[] propertyList = typeSource.GetProperties(); for (int index = 0; index < propertyList.Length; index++) { Type tempPropertySourceValueType = null; object tempPropertySourceValue = null; Type tempPropertyTargetValueType = null; object tempPropertyTargetValue = null; //get rid of indexers if (propertyList[index].GetIndexParameters().Length == 0) { tempPropertySourceValue = propertyList[index].GetValue(source, null); tempPropertyTargetValue = propertyList[index].GetValue(target, null); } if (tempPropertySourceValue != null) tempPropertySourceValueType = tempPropertySourceValue.GetType(); if (tempPropertyTargetValue != null) tempPropertyTargetValueType = tempPropertyTargetValue.GetType(); //if the property is a list IList ilistSource = tempPropertySourceValue as IList; IList ilistTarget = tempPropertyTargetValue as IList; if (ilistSource != null || ilistTarget != null) { if (ilistSource != null) ilistSource.MergeList(ilistTarget); else propertyList[index].SetValue(source, ilistTarget, null); } //if the property is a Dto else if (tempPropertySourceValue != null || tempPropertyTargetValue != null) { if (tempPropertySourceValue != null) tempPropertySourceValue.MergeObject(tempPropertyTargetValue); else propertyList[index].SetValue(source, tempPropertyTargetValue, null); } } } } return source; } } /* However, this works when the source property is null, if target has it, it will copy that to source. IT can still be improved to merge when inconsistencies are there e.g. if FirstName="Tiju" and FirstName="John" Any commments appreciated. Thanks TJ */.net 2.0 object List Class c # merge ojbect graph readflection
Software Engineer
Noida