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

标签 c# serialization xmlserializer

我想序列化以下内容:

[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] 时才会出现异常。

请帮忙!

谢谢!

最佳答案

对于编辑过的问题,看起来你有一个循环。请注意,XmlSerializer 是一个 序列化器,而不是一个 序列化器,因此它会失败。这里通常的修复是禁用向上遍历:

[XmlIgnore]
public ItemInfo parentItemInfo;

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

关于异常 - 你需要查看 InnerException - 它可能会准确地告诉你这一点,例如在你的 (catch ex) 中:

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

我猜它实际上是:

"A circular reference was detected while serializing an object of type ItemInfoA."


关于设计的更多一般,老实说,(公共(public)领域,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
{
}

根据要求,这里有一个一般的(不是特定于问题的)递归设置父级在 hive 中的说明(为了好玩,我在堆上使用深度优先;对于布雷斯优先,只需将 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);
            }                
        }
    }
}

关于C# xml serializer - 序列化派生对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4859935/

相关文章:

c# - 如何了解 zip 文件是否损坏或仍在传输

java - 如何将 java 对象序列化为 javax.JSON 或从 javax.JSON 反序列化

c# - 为什么复杂字符串(字符串化的 json 数据)不被接受为 Web API 方法的 POST 参数,而简单字符串却可以?

c# - 解释 "finally"在 try-catch-finally block 中的使用

c# - 如何覆盖具有继承类型的接口(interface)属性

c# - 将C#连接到MYSQL数据库?

c# - 使用 xsd.exe 反序列化 - 如何反序列化为对象,而不是数据集?

c# - XML 序列化和命名空间前缀

java - 在 C# 中序列化 Java 对象和反序列化

c# - XmlSerializer 和工厂创建的元素