簡體   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