简体   繁体   English

C#xml序列化程序 - 序列化派生对象

[英]C# xml serializer - serialize derived objects

I want to serialize the following: 我想序列化以下内容:

[Serializable]
[DefaultPropertyAttribute("Name")]
[XmlInclude(typeof(ItemInfo))]
[XmlInclude(typeof(ItemInfoA))]
[XmlInclude(typeof(ItemInfoB))] 
public class ItemInfo
{
    public string name;

    [XmlArray("Items"), XmlArrayItem(typeof(ItemInfo))]
    public ArrayList arr;

    public ItemInfo parentItemInfo;
}

[Serializable]
[XmlInclude(typeof(ItemInfo))]
[XmlInclude(typeof(ItemInfoA))]
[XmlInclude(typeof(ItemInfoB))] 
public class ItemInfoA : ItemInfo
{
...
}

[Serializable]
[XmlInclude(typeof(ItemInfo))]
[XmlInclude(typeof(ItemInfoA))]
[XmlInclude(typeof(ItemInfoB))] 
public class ItemInfoB : ItemInfo
{
...
}

The class itemInfo describes a container which can hold other itemInfo objects in the array list, the parentItemInfo describes which is the parent container of the item info. itemInfo描述了一个容器,它可以容纳数组列表中的其他itemInfo对象, parentItemInfo描述了哪个是项信息的父容器。

Since ItemInfoA and ItemInfoB derive from ItemInfo they can also be a member of the array list and the parentItemInfo , therefore when trying to serialize these objects (which can hold many objects in hierarchy) it fails with exception 由于ItemInfoAItemInfoB派生自ItemInfo因此它们也可以是数组列表和parentItemInfo ,因此在尝试序列化这些对象(可以在层次结构中保存许多对象)时,它会失败并出现异常

IvvalidOperationException.`there was an error generating the xml file `

My question is: 我的问题是:

What attributes do I need to add the ItemInfo class so it will be serializable? 添加ItemInfo类需要哪些属性才能序列化?

Note: the exception is only when the ItemInfo[A]/[B] are initialized with parentItemInfo or the arrayList. 注意:仅当使用parentItemInfo或arrayList初始化ItemInfo [A] / [B]时parentItemInfo出现异常。

Help please! 请帮助!

Thanks! 谢谢!

With the edited question, it looks like you have a loop. 通过编辑的问题,看起来你有一个循环。 Note that XmlSerializer is a tree serializer, not a graph serializer, so it will fail. 请注意, XmlSerializer序列化器,而不是图形序列化器,因此它将失败。 The usual fix here is to disable upwards traversal: 这里通常的解决方法是禁用向上遍历:

[XmlIgnore]
public ItemInfo parentItemInfo;

Note you will have to manually fixup the parents after deserialization, of course. 请注意,当然,您必须在反序列化后手动修复父项。

Re the exception - you need to look at the InnerException - it probably tells you exactly this, for example in your (catch ex) : 重新异常 - 您需要查看InnerException - 它可能会告诉您这一点,例如在您的(catch ex)

while(ex != null) {
    Debug.WriteLine(ex.Message);
    ex = ex.InnerException;
}

I'm guessing it is actually: 我猜它实际上是:

"A circular reference was detected while serializing an object of type ItemInfoA." “序列化ItemInfoA类型的对象时检测到循环引用。”


More generally on the design, honestly that (public fields, ArrayList , settable lists) is bad practice; 一般地说 ,在设计上,老实说(公共字段, ArrayList ,可设置列表)是不好的做法; here's a more typical re-write that behaves identically : 这是一个更典型的重写,行为相同

[DefaultPropertyAttribute("Name")]
[XmlInclude(typeof(ItemInfoA))]
[XmlInclude(typeof(ItemInfoB))] 
public class ItemInfo
{
    [XmlElement("name")]
    public string Name { get; set; }

    private readonly List<ItemInfo> items = new List<ItemInfo>();
    public List<ItemInfo> Items { get { return items; } }

    [XmlIgnore]
    public ItemInfo ParentItemInfo { get; set; }
}
public class ItemInfoA : ItemInfo
{
}
public class ItemInfoB : ItemInfo
{
}

as requested, here's a general (not question-specific) illustration of recursively setting the parents in a hive (for kicks I'm using depth-first on the heap; for bredth-first just swap Stack<T> for Queue<T> ; I try to avoid stack-based recursion in these scenarios): 根据要求,这里是一个一般(不是问题特定的)插图,用于递归设置蜂巢中的父母(对于踢我在堆上使用深度优先;对于bredth-first只是交换Stack<T>用于Queue<T> ;我尝试在这些场景中避免基于堆栈的递归):

public static void SetParentsRecursive(Item parent)
{
    List<Item> done = new List<Item>();
    Stack<Item> pending = new Stack<Item>();
    pending.Push(parent);
    while(pending.Count > 0)
    {
        parent = pending.Pop();
        foreach(var child in parent.Items)
        {
            if(!done.Contains(child))
            {
                child.Parent = parent;
                done.Add(child);
                pending.Push(child);
            }                
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM