而不是定义这是一个序列化问题(如何序列化和反序列化对父代的反向引用),将其定义为类设计问题可能是有意义的,即
由于家长和孩子的层次结构,如何保证孩子的父母背引用自动将其添加到他们的父母时设置是否正确?
一旦以这种方式定义问题并解决问题,在反序列化和程序化数据创建期间应保证正确性,因为父反向引用永远不需要序列化或反序列化。
完成此操作的一种方法是定义一个自定义子类Collection<T>
,该子类自动设置并清除父回引用。
首先,定义以下接口和收集:
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);
}
}
然后定义您的MyObject
和RootObject
类型如下:
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> ChildObjects
在MyObject
是启动LY。 Json.NET(和XmlSerializer
就此而言)可以成功反序列化一个只能获得预分配的集合。
方法ShouldSerializeChildObjects()
是可选的,并防止对空的ChildObjects []
数组值进行序列化。
由于ObservableCollection<T>
本身就是Collection<T>
一个子类,你可以选择它作为基类为ChildCollection<TParent, TChild>
,如果你需要通知项目时添加或删除。
Parent
属性标有[JsonIgnore]
以防止其序列化。
样本fiddle包括一些基本的单元测试。
来源
2017-10-19 19:52:40
dbc
您是否尝试将['PreserveReferencesHandling'](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_PreserveReferencesHandling.htm)设置设置为'Objects'?如果你这样做,你不应该需要一个转换器;引用将通过特殊的'$ id'和'$ ref'元属性保存在JSON中。 –
@BrianRogers,我想过为“Object Class”添加一个“Parent Object”属性。这样我就可以得到父母的参考。这个参考资料是否适合这种用途? (如果它可以作为JSON文件上父节点的引用) –
是的,您的子对象可以引用父对象,反之亦然,如果您在序列化和反序列化时都使用该设置,它应该可以工作。 –