简体   繁体   English

如何序列化/反序列化IList集合的类包装器?

[英]How to serialize/deserialize class-wrapper of IList collection?

I have base class Control , which contains a property public ControlCollection Controls; 我有Control基类,它包含一个public ControlCollection Controls;的属性public ControlCollection Controls; :

public abstract class Control { 
    ...
    public virtual string Name { get: set; }
    public ControlCollection Controls;
    public Control parent = null;
    ...
}

ControlCollection is my own class, which implemets IList<Control> : ControlCollection是我自己的类,实现IList<Control>

public sealed class ControlCollection : IList<Control>, IMySerializable {       
    public int Count => _controls.Count;
    public bool IsReadOnly { get; } = false;
    public Control Parent;

    private List<Control> _controls = new List<Control>();

    public ControlCollection(Control parent) {
        Parent = parent ?? throw new ArgumentNullException("parent");
    }

    public Control this[int index] {
        get => _controls[index];
        set => _controls[index] = value;
    }

    public void Add(Control child) {
        child.parent = Parent;
        _controls.Add(child);
    }

    ...
}

If I change a type of property Controls from ControlCollection to List<Control> , then code below will form a correct XML file 如果我将Controls的属性类型从ControlCollection更改为List<Control> ,则下面的代码将形成正确的XML文件

// temp data
Control rootObj = new Button();  rootObj.Name = "111";
Control obj2 = new Label();   obj2.Name = "222";
Control obj3 = new Button();  obj3.Name = "333";    
rootObj.Controls.Add(obj2); 
rootObj.Controls.Add(obj3);

List<Type> list = new List<Type>();
rootObj.Controls.ForEach(child => child.DoActionWithChildren(node => {
    list.Add(node.GetType());
}));

list.Add(typeof(Button));
list = list.Distinct().ToList();

// trying to set xml attributes. 'Controls' property will be a root of collection
var attributes = new XmlAttributes();
list.ForEach(t => attributes.XmlArrayItems.Add(new XmlArrayItemAttribute(t)));
var attrOverride = new XmlAttributeOverrides();
attrOverride.Add(typeof(Control), "Controls", attributes); 

// save data to file    
using(StreamWriter sw = new StreamWriter("path/to/xml/file.xml", false, Encoding.UTF8)) {
    XmlSerializer xs = new XmlSerializer(typeof(Control), attrOverride);        
    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
    ns.Add(string.Empty, string.Empty);
    xs.Serialize(sw, rootObj, ns);  
}

/* ---------------------- */
output:

<?xml version="1.0" encoding="utf-8"?>
<Control d1p1:type="Button" xmlns:d1p1="http://www.w3.org/2001/XMLSchema-instance">
  <Controls>
    <Control d1p1:type="Label">
      <Controls />      
      <Name>22222</Name>
    </Control>
    <Control d1p1:type="Button">
      <Controls />
      <Name>32333</Name>      
    </Control>
  </Controls>  
  <Name>1111</Name>  
</Control>

But if a type of property Controls is ControlCollection , then XML will be cut off: 但是,如果Controls的属性类型为ControlCollection ,则XML将被截断:

<?xml version="1.0" encoding="utf-8"?>
<Button>
  <Controls>
    <Control d3p1:type="Label" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance">
      <Controls />

I tried to change the type: attrOverride.Add(typeof(ControlCollection), "Controls", attributes); 我试图更改类型: attrOverride.Add(typeof(ControlCollection), "Controls", attributes); , but this doesn't work. ,但这不起作用。


What should I do to serialize ControlCollection properly? 如何正确序列化ControlCollection And what should I know to properly deserialize it afterwards? 然后我应该知道如何适当地反序列化呢?

Well, I fixed it. 好吧,我修好了。 It turned out that I had a circular reference because of a property public Control parent = null; 原来我有一个循环引用,因为有一个属性public Control parent = null; in my base class. 在我的基础课上。 I wrote an attribute [XmlIgnore] and it worked, even with attrOverride.Add(typeof(ControlCollection), "Controls", attributes); 我写了一个属性[XmlIgnore] ,即使使用attrOverride.Add(typeof(ControlCollection), "Controls", attributes); ,它也可以正常工作attrOverride.Add(typeof(ControlCollection), "Controls", attributes);

The reason why I didn't see this error is that my original project is a Unity project. 我没有看到此错误的原因是我的原始项目是Unity项目。 And Unity didn't show me that error. 而且Unity没有向我显示该错误。 When I made a simple C# Console application - it showed me that error. 当我制作一个简单的C#控制台应用程序时-它向我显示了该错误。 It's sad but true. 这是可悲但真实的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM