展平父/子对象链,沿途合并值
本文关键字:合并 对象 | 更新日期: 2023-09-27 18:27:22
我们已经关注这个问题很长时间了,浪费了宝贵的时间。
我们有这些对象,让我们称它们为组件。我们的应用程序允许您在现有组件的基础上创建新组件 父级的所有值都是"继承的"(读作:可通过 现在,我想从上到下将其展开,将父对象的现有值用于子对象上的任何空值。 值得注意的是:没有子属性,只有子属性知道父属性。家长不知道孩子。 如何在不使用丑陋的component.Parent
属性访问),除非重写一个值——例如,您想给它一个新名称,但保留其余的父级值。// Exiting parent-child object chain
BaseObject {Id = 1, Name = "Base", Description = "Base description", Notes = "Awesome object", ParentId = null}
ChildObject1 {Id = 2, Name = "", Description = "", Notes = "", ParentId = 1}
ChildObject2 {Id = 3, Name = "Custom Name", Description = "", Notes = "", ParentId = 2}
ChildObject3 {Id = 4, Name = "", Description = "Final object", Notes = "", ParentId = 3}
// End result after flattening/merging
ChildObject3 {Id = 4, Name = "Custom Name", Description = "Final object", Notes = "Awesome object", ParentId = 3}
while(child.Parent != null)
构造和创建previousComponent
、currentComponent
等对象来跟踪集合值的情况下解决此问题。
递归DeepCopy
方法怎么样,比如:
public class ComponentClass()
{
public ComponentClass DeepCopy(ComponentClass comp)
{
CopyAllNonEmptyPropertiesTo(comp);
if (comp.StillHasEmptyProperties())
return Parent.DeepCopy(comp);
else
return comp;
}
}
创建数据对象的字典,以便查找父对象。
对于您拥有的每个项,在以下情况下对父值进行递归查找:
- 您没有目标属性之一的值
- 你有父母
例如(Dump()命令来自LinqPad)
var data = new List<Bob>
{
new Bob { Id = 1, Name = "Base", Description = "Base description", Notes = "Awesome object", ParentId = null },
new Bob { Id = 2, Name = "", Description = "", Notes = "", ParentId = 1 },
new Bob { Id = 3, Name = "Custom Name", Description = "", Notes = "", ParentId = 2 },
new Bob { Id = 4, Name = "", Description = "Final object", Notes = "", ParentId = 3 },
};
var map = data.ToDictionary(d => d.Id, d => d);
data.ForEach(row => CopyFromParent(map, row, row.ParentId.HasValue ? map[row.ParentId.Value] : null));
data.Dump();
}
void CopyFromParent(Dictionary<int, Bob> map, Bob target, Bob current)
{
// set properties
if (current != null && string.IsNullOrEmpty(target.Name) && !string.IsNullOrEmpty(current.Name)) target.Name = current.Name;
if (current != null && string.IsNullOrEmpty(target.Description) && !string.IsNullOrEmpty(current.Description)) target.Description = current.Description;
if (current != null && string.IsNullOrEmpty(target.Notes) && !string.IsNullOrEmpty(current.Notes)) target.Notes = current.Notes;
// dive deeper if we need to, and if we can
var needToDive = string.IsNullOrEmpty(target.Name) || string.IsNullOrEmpty(target.Description) || string.IsNullOrEmpty(target.Notes);
var canDive = current != null && current.ParentId.HasValue && map.ContainsKey(current.ParentId.Value);
if (needToDive && canDive)
{
CopyFromParent(map, target, map[current.ParentId.Value]);
}
}
class Bob
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public int? ParentId { get; set; }
}