gpt4 book ai didi

c# - 使用 JsonConverter 存储/检索父子关系

转载 作者:行者123 更新时间:2023-11-30 23:08:04 27 4
gpt4 key购买 nike

我有一个带有子对象数组的 JSON 结构(包括 POCO 类),如下所示:

    "Object": [    {        "Name": "TestA",        "ChildObjects": [        {            "Name": "TestB"            "ChildObjects": [                {                    "Name": "TestC"                    ...                }            ]        }    ]

反序列化时,我想保留对父级的引用我刚刚创建的对象。

但我必须在填充子对象之前获得此引用。(在我填充子对象的那一刻,我必须具有可访问的父对象结构/引用)

我试过使用自定义 JsonConverter,但是我找不到存储或检索这种关系的方法。

最佳答案

与其将其定义为序列化问题(如何序列化和反序列化对父对象的反向引用),不如将其定义为类设计问题,即

Given a hierarchy of parents and children, how to ensure that child back-references to parents are automatically set correctly when adding them to their parents?

一旦以这种方式定义并解决了问题,就应该在反序列化和编程数据创建期间确保正确性,因为永远不需要序列化或反序列化父反向引用。

实现此目的的一种方法是定义 Collection<T> 的自定义子类自动设置和清除父反向引用。

首先,定义如下接口(interface)和集合:

public interface IHasParent<TParent> where TParent : class
{
TParent Parent { get; }

void OnParentChanging(TParent newParent);
}

public class ChildCollection<TParent, TChild> : Collection<TChild>
where TChild : IHasParent<TParent>
where TParent : class
{
readonly TParent parent;

public ChildCollection(TParent parent)
{
this.parent = parent;
}

protected override void ClearItems()
{
foreach (var item in this)
{
if (item != null)
item.OnParentChanging(null);
}
base.ClearItems();
}

protected override void InsertItem(int index, TChild item)
{
if (item != null)
item.OnParentChanging(parent);
base.InsertItem(index, item);
}

protected override void RemoveItem(int index)
{
var item = this[index];
if (item != null)
item.OnParentChanging(null);
base.RemoveItem(index);
}

protected override void SetItem(int index, TChild item)
{
var oldItem = this[index];
if (oldItem != null)
oldItem.OnParentChanging(null);
if (item != null)
item.OnParentChanging(parent);
base.SetItem(index, item);
}
}

然后定义你的MyObjectRootObject类型如下:

public class MyObject : IHasParent<MyObject>
{
readonly ChildCollection<MyObject, MyObject> childObjects;

public MyObject() { this.childObjects = new ChildCollection<MyObject, MyObject>(this); }

public string Name { get; set; }

public IList<MyObject> ChildObjects { get { return childObjects; } }

#region IHasParent<MyObject> Members

[JsonIgnore]
public MyObject Parent { get; private set; }

public void OnParentChanging(MyObject newParent)
{
Parent = newParent;
}

#endregion

// Added to suppress serialization of empty ChildObjects collections to JSON.
public bool ShouldSerializeChildObjects() { return childObjects.Count > 0; }
}

public class RootObject
{
public RootObject() { this.Object = new List<MyObject>(); }

public List<MyObject> Object { get; set; }
}

注意事项:

  • 合集IList<MyObject> ChildObjectsMyObject是只读的。 Json.NET(和 XmlSerializer 就此而言)可以成功反序列化预分配的预分配集合。

  • 方法ShouldSerializeChildObjects()是可选的,防止序列化空 ChildObjects []数组值。

  • ObservableCollection<T> 本身是 Collection<T> 的子类,您可以选择它作为 ChildCollection<TParent, TChild> 的基类如果您需要在添加或删除项目时收到通知。

  • Parent属性标有 [JsonIgnore] 以防止其序列化。

样本 fiddle包括一些基本的单元测试。

关于c# - 使用 JsonConverter 存储/检索父子关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46774119/

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