繁体   English   中英

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

[英]C# xml serializer - serialize derived objects

我想序列化以下内容:

[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
{
...
}

itemInfo描述了一个容器,它可以容纳数组列表中的其他itemInfo对象, parentItemInfo描述了哪个是项信息的父容器。

由于ItemInfoAItemInfoB派生自ItemInfo因此它们也可以是数组列表和parentItemInfo ,因此在尝试序列化这些对象(可以在层次结构中保存许多对象)时,它会失败并出现异常

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

我的问题是:

添加ItemInfo类需要哪些属性才能序列化?

注意:仅当使用parentItemInfo或arrayList初始化ItemInfo [A] / [B]时parentItemInfo出现异常。

请帮助!

谢谢!

通过编辑的问题,看起来你有一个循环。 请注意, XmlSerializer序列化器,而不是图形序列化器,因此它将失败。 这里通常的解决方法是禁用向上遍历:

[XmlIgnore]
public ItemInfo parentItemInfo;

请注意,当然,您必须在反序列化后手动修复父项。

重新异常 - 您需要查看InnerException - 它可能会告诉您这一点,例如在您的(catch ex)

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

我猜它实际上是:

“序列化ItemInfoA类型的对象时检测到循环引用。”


一般地说 ,在设计上,老实说(公共字段, ArrayList ,可设置列表)是不好的做法; 这是一个更典型的重写,行为相同

[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
{
}

根据要求,这里是一个一般(不是问题特定的)插图,用于递归设置蜂巢中的父母(对于踢我在堆上使用深度优先;对于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