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

发布于 2024-10-14 23:56:48 字数 1229 浏览 2 评论 0原文

我想序列化以下内容:

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

请帮忙!

谢谢!

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.

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

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?

Note: the exception is only when the ItemInfo[A]/[B] are initialized with parentItemInfo or the arrayList.

Help please!

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笑叹一世浮沉 2024-10-21 23:56:48

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

[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交换为Queue;在这些情况下,我尝试避免基于堆栈的递归):

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);
            }                
        }
    }
}

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. 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):

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."


More generally on the design, honestly that (public fields, ArrayList, settable lists) is bad practice; 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):

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);
            }                
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文