Почему моя публичная собственность не сериализована 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]
Любое из них не приведет к сериализации
Ответ 2
Точка о геттере + сеттер делается в третьем абзаце на странице Intro to Xml Serialization". Это на самом деле в выписке. Не пропустите!
Сериализация внутри-XML http://www.freeimagehosting.net/uploads/2f04fea2db.png
(имея слишком много удовольствия с Freeimagehosting.net)
Ответ 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
и выполнить сериализацию вручную, а также воспользоваться параметрами сериализации и, наоборот, десериализовать их с помощью назначения конструкторов/частных.