Почему моя публичная собственность не сериализована XmlSerializer?

Это один из тех, с кем я боролся целую вечность, поэтому подумал, что я где-нибудь буду документировать. (Извинения за вопрос и ответ на вопрос.)

(С#.net 2.0) У меня был класс, который был сериализован XmlSerializer, я добавил новое публичное свойство, но оно не включалось в выходной XML.

Он не упоминается в документах, где бы я ни находил, но общедоступные свойства должны иметь набор, а также сериализоваться! Я предполагаю, что это связано с тем, что предполагается, что если вы собираетесь сериализовать, вы захотите десериализовать из того же файла, так что только сериализует свойства, которые имеют как набор, так и get.

Ответ 1

Как уже упоминалось, большинство свойств должны иметь как геттер, так и сеттер; основным исключением является список - например:

private readonly List<Foo> bar = new List<Foo>();
public List<Foo> Bar {get { return bar; } } // works fine

который будет работать нормально; однако, если XmlSerializer находит сеттер - он требует, чтобы он был общедоступным; ниже будет не:

public List<Foo> Bar {get; private set;} // FAIL

Другие причины, по которым он не может сериализоваться:

  • он не является общедоступным с get и set (или является readonly для поля)
  • он имеет атрибут [DefaultValue] и имеет это значение
  • у него есть общедоступный метод bool ShouldSerializeFoo(), который возвращает false
  • у него есть общедоступное свойство bool FooSpecified {get;set;} или поле, которое возвращает false
  • помечено [XmlIgnore]
  • отмечено [Obsolete]

Любое из них не приведет к сериализации

Ответ 3

если вы не хотите внедрять правильные Setters (потому что, возможно, вы не хотите десериализовать или изменять значение объектов), вы можете просто использовать фиктивные сеттеры, подобные этому set { }, так что XMLSerializer работает, но ничего происходит, если вы используете Setter...

т.е.

public string ID { get { return _item.ID.ToString(); } set { } }

Ответ 4

Также свойства, возвращающие значение null, не сериализуются!

Ответ 5

И если ваш класс наследует список, а также имеет свои собственные члены, только элементы списка становятся сериализованными. Данные, присутствующие в ваших членах класса, не записываются. Подумал об этом!

Ответ 6

Еще одна вещь, чтобы добавить о сериализации коллекций:

XmlSerializer игнорирует коллекции интерфейсов!

И под этим я подразумеваю игнорировать. Пока вы получите исключение для строки, например:

public IFoo Foo { get; set; }

вы не получите исключение для:

public ICollection<IFoo> LotsOfFoos { get { return this.fooBackingField; } }

Ответ 7

Вы можете реализовать IXmlSerializer и выполнить сериализацию вручную, а также воспользоваться параметрами сериализации и, наоборот, десериализовать их с помощью назначения конструкторов/частных.