Первая проблема связана с элементом XmlRoot
.Я ожидал, что атрибут version
появится внутри тега XMLRoot
, но его нет.
Как объяснено в Введение в сериализацию XML , XmlSerializer
не будет сериализовать элемент const
, даже если public:
Сериализация XML сериализует только открытые поля и значения свойств объекта в поток XML.XML-сериализация не включает информацию о типе.
Сериализация XML не преобразует методы, индексаторы, частные поля или свойства только для чтения (кроме коллекций только для чтения).Чтобы сериализовать все поля и свойства объекта, как публичные, так и приватные, используйте DataContractSerializer вместо XML-сериализации.
Самый простой способ обойти это - добавить суррогатное свойство для версии, например:
public const string version = "D";
[XmlAttribute("version")]
[System.ComponentModel.Browsable(false), System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never), System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public string Version { get { return version; } set { /* Do nothing */ } }
Свойство должно быть публичным, но вы можете уменьшить его видимость с помощью атрибутов Browsable
, EditorBrowsable
и DebuggerBrowsable
.
Вторая проблема - это порядок элементов (хорошо, это не большая проблема, поскольку теги не зависят от порядка) Я попытался использовать атрибут XmlElement(Order=nn)
, чтобы вызвать его, но ятолько что получил ряд Reflection
исключений.
Вы не предоставили пример этого, но я смог воспроизвести следующую проблему.Если я установлю XmlArrayAttribute.Order
на некоторые , но не все членов коллекции SchematicExport
, я получу следующее исключение:
System.InvalidOperationException: There was an error reflecting type 'SchematicExport'.
---> System.InvalidOperationException: Inconsistent sequencing: if used on one of the class's members, the 'Order' property is required on all particle-like members, please explicitly set 'Order' using XmlElement, XmlAnyElement or XmlArray custom attribute on class member 'nets'.
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
Демонстрационная скрипка # 1 здесь .
Решение состоит в том, чтобы последовать совету в сообщении об исключении и применить атрибут порядка ко всем сериализуемым членам в классе.
Таким образом, SchematicExport
должен выглядеть примерно так:
[XmlRoot(ElementName = "export")]
public partial class SchematicExport
{
public const string version = "D";
[XmlAttribute("version")]
[System.ComponentModel.Browsable(false), System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never), System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public string Version { get { return version; } set { /* Do nothing */ } }
[XmlElement(Order = 1)]
public Design design { get; set; }
[XmlArray(Order = 2)]
[XmlArrayItem(typeof(Component), ElementName = "comp")]
public List<Component> components;
[XmlArray(Order = 3)]
[XmlArrayItem(typeof(LibPart), ElementName = "libpart")]
public List<LibPart> libparts;
[XmlArray(Order = 4)]
[XmlArrayItem(typeof(Library), ElementName = "library")]
public List<Library> libraries;
[XmlArray(Order = 5)]
[XmlArrayItem(typeof(Net), ElementName = "net")]
public List<Net> nets;
}
Обратите внимание, что установка порядка элементов не только переупорядочивает элементы во время сериализации, но также требует , что онибыть в таком порядке во время десериализации.
Кстати, в SchematicExport.Serialize(string)
вам нужно закрыть StreamWriter
.Самый простой способ сделать это с помощью оператора using
:
public void Serialze(string filename)
{
XmlSerializer _xmlSerializer = new XmlSerializer(typeof(SchematicExport));
// FIXED ensure the file is closed.
using (var _textWriter = new StreamWriter(filename))
{
_xmlSerializer.Serialize(_textWriter, this);
}
}
Первая версия этого метода, показанная в вашем вопросе, этого не делает.
Демонстрационная скрипка № 2 здесь .