gln*_*gln 3 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
{
...
}
Run Code Online (Sandbox Code Playgroud)
该类itemInfo描述了一个容器,它可以容纳itemInfo数组列表中的其他对象,该parentItemInfo描述是项信息的父容器.
既然ItemInfoA并且ItemInfoB派生自ItemInfo它们也可以是数组列表的成员parentItemInfo,因此当尝试序列化这些对象(可以在层次结构中保存许多对象)时,它会失败并出现异常
IvvalidOperationException.`there was an error generating the xml file `
Run Code Online (Sandbox Code Playgroud)
我的问题是:
添加ItemInfo类需要哪些属性才能序列化?
注意:仅当使用parentItemInfo或使用arrayList 初始化ItemInfo [A]/[B]时才会出现异常.
请帮忙!
谢谢!
通过编辑的问题,看起来你有一个循环.请注意,这XmlSerializer是一个树序列化器,而不是图形序列化器,因此它将失败.这里通常的解决方法是禁用向上遍历:
[XmlIgnore]
public ItemInfo parentItemInfo;
Run Code Online (Sandbox Code Playgroud)
请注意,当然,您必须在反序列化后手动修复父项.
重新例外 - 您需要查看InnerException- 它可能会告诉您这一点,例如在您的(catch ex):
while(ex != null) {
Debug.WriteLine(ex.Message);
ex = ex.InnerException;
}
Run Code Online (Sandbox Code Playgroud)
我猜它实际上是:
"序列化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
{
}
Run Code Online (Sandbox Code Playgroud)
根据要求,这里是一个一般的(不是特定于问题的)插图,用于递归设置蜂巢中的父母(对于踢我在堆上使用深度优先;对于bredth-first just swap Stack<T>for 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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1344 次 |
| 最近记录: |