Открытые поля / свойства класса, производного от BindingList <T>, не будут сериализироваться - PullRequest
2 голосов
/ 04 августа 2009

Я пытаюсь сериализовать класс, производный от 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?

Ответы [ 3 ]

3 голосов
/ 05 августа 2009

Короткий ответ здесь заключается в том, что .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 голосов
/ 05 августа 2009

XML-сериализация обрабатывает коллекции особым образом и никогда не сериализует поля или свойства коллекции, только элементы.

Вы можете либо:

  • реализовать IXmlSerializable для генерации и анализа XML самостоятельно (но это много работы)
  • обернуть ваш BindingList в другой класс, в котором вы объявляете свои настраиваемые поля (как предложено в speps)
1 голос
/ 05 августа 2009

Это известная проблема с сериализацией 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>();
}

Это означает, что вы можете добавлять этажи с помощью этажей. Добавьте, и вы получите желаемый результат, но, надеюсь, я его не пробовал. Помните, что игра с атрибутами - это ключ к сериализации XML.

...