gpt4 book ai didi

.net - 合并 .net 对象图

转载 作者:行者123 更新时间:2023-12-02 05:13:41 25 4
gpt4 key购买 nike

有没有人遇到过需要将一个对象与另一个相同类型的对象合并,从而合并完整的对象图的场景。例如如果我有一个人对象,一个人对象有名字,另一个有姓氏,可以通过某种方式将这两个对象合并为一个对象。

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"
}

我遇到过这种类型的需求,我写了一个扩展方法来做同样的事情。

    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;
}


}

但是,这在源属性为空时起作用,如果目标有它,它将把它复制到源。当存在不一致时,IT 仍然可以改进以合并,例如如果 FirstName="Tiju"和 FirstName="John"

感谢任何评论。

谢谢田杰

最佳答案

您的代码看起来很讨厌。您确定需要这样的通用模型吗?您打算单独合并多个 Person 对象吗?如果是这样,合并要求是否完全相同?如果您需要合并其他类型,更改是它们必须以不同的方式合并。也许你应该选择没有反射的设计。这是另一个想法:

public interface IMergable<T>
{
T MergeWith(T other);
}

public interface IEntity
{
object EntityId { get; }
}

public class Person : IMergable<Person>, IEntity
{
public int Id { get; set; }

object IEntity.EntityId { get { return this.Id; } }

public Person MergeWith(Person other)
{
var mergedperson = new Person();

// Do merging here, and throw InvalidOperationException
// when objects can not be merged.

return mergedPerson;
}
}

你的扩展方法看起来像这样:

public static IEnumerable<T> MergeList<T>(this IEnumerable<T> left,
IEnumerable<T> right)
where T : IMergable<T>, IEntity
{
return
from leftEntity in left
from rightEntity in right
where leftEntity.EntityId.Equals(rightEntity.EntityId)
select leftEntity.MergeWith(rightEntity);
}

关于.net - 合并 .net 对象图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3051948/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com