【问题标题】:Public fields/properties of a class derived from BindingList<T> wont serialize从 BindingList<T> 派生的类的公共字段/属性不会序列化
【发布时间】:2009-08-04 04:36:41
【问题描述】:

我正在尝试序列化一个派生自 BindingList(Floor) 的类,其中 Floor 是一个仅包含属性 Floor.Height 的简单类

这是我的课程的简化版

[Serializable]
[XmlRoot(ElementName = "CustomBindingList")]
public class CustomBindingList:BindingList<Floor>
{
    [XmlAttribute("publicField")]
    public string publicField;
    private string privateField;

    [XmlAttribute("PublicProperty")]
    public string PublicProperty
    {
        get { return privateField; }
        set { privateField = value; }
    }
}

我将使用以下代码序列化 CustomBindingList 的一个实例。

XmlSerializer ser = new XmlSerializer(typeof(CustomBindingList));
StringWriter sw = new StringWriter();

CustomBindingList cLIst = new CustomBindingList();

Floor fl;

fl = new Floor();
fl.Height = 10;
cLIst.Add(fl);

fl = new Floor();
fl.Height = 10;    
cLIst.Add(fl);

fl = new Floor();
fl.Height = 10;
cLIst.Add(fl);

ser.Serialize(sw, cLIst);

string testString = sw.ToString();

然而,上面的 testString 最终被设置为以下 XML:

<CustomBindingList xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
    <Floor Height="10" />
    <Floor Height="10" />
    <Floor Height="10" />
</CustomBindingList>"

如何让“publicField”或“publicProperty”也序列化?

【问题讨论】:

  • 从几乎任何系统集合类派生都是一个非常糟糕的主意。实现一个不扩展的接口。
  • 我不想从 IBindingList 派生,因为它不是泛型的,而且我不喜欢非泛型集合,每次我想做某事时都必须转换为我的真实对象类型。
  • [Serializable] 属性被 XML 序列化忽略。你应该删除它。

标签: c# serialization xml-serialization bindinglist


【解决方案1】:

这里的简短回答是,.NET 通常期望某些东西成为集合xor具有属性。这体现在几个地方:

  • xml序列化;集合的属性未序列化
  • 数据绑定;您不能将数据绑定到集合上的属性,因为它会隐式地将您带到第一个项目

在 xml 序列化的情况下,如果您认为它可能只是客户端的 SomeType[] 是有道理的......额外的数据会去哪里?

常见的解决方案是封装一个集合——即,而不是

public class MyType : List<MyItemType> // or BindingList<...>
{
    public string Name {get;set;}
}

public class MyType
{
    public string Name {get;set;}
    public List<MyItemType> Items {get;set;} // or BindingList<...>
}

通常我不会在集合属性上使用 set,但 XmlSerializer 需要它...

【讨论】:

    【解决方案2】:

    XML 序列化以特定方式处理集合,从不序列化集合的字段或属性,仅序列化项。

    你可以:

    • 实现 IXmlSerializable 以自己生成和解析 XML(但工作量很大)
    • 将 BindingList 包装在另一个类中,在其中声明自定义字段(如 speps 所建议的那样)

    【讨论】:

    • 我最终实现了 IXMLSerializable。包装/封装 BindingList 的问题在于,使用 BindingList 的关键在于它具有允许它附加到 GUI 元素(如 DataGrid)的事件,非常容易。因此,如果我封装了 BindingList,则生成的类将不会有任何这些事件。
    【解决方案3】:

    这是 XML 序列化和从集合继承的已知问题。

    您可以在此处阅读更多信息:http://social.msdn.microsoft.com/Forums/en-US/asmxandxml/thread/0d94c4f8-767a-4d0f-8c95-f4797cd0ab8e

    你可以试试这样的:

    [Serializable]
    [XmlRoot]
    public class CustomBindingList
    {
        [XmlAttribute]
        public string publicField;
        private string privateField;
    
        [XmlAttribute]
        public string PublicProperty
        {
            get { return privateField; }
            set { privateField = value; }
        }
    
        [XmlElement]
        public BindingList<Floor> Floors = new BindingList<Floor>();
    }
    

    这意味着您可以使用 Floors.Add 添加楼层,您将获得所需的结果,但我希望,我没有尝试过。请记住,使用属性是 XML 序列化的关键。

    【讨论】:

      猜你喜欢
      • 2012-04-16
      • 2019-05-10
      • 2014-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多