Оборачивание сериализованных свойств в дополнительные элементы с .NET XML-сериализацией - PullRequest
1 голос
/ 04 августа 2009

Я использую C # + VSTS2008 + .Net 3.0 для сериализации XML. Код работает отлично. Здесь ниже мой код и текущие результаты XML сериализации.

Теперь я хочу добавить два дополнительных слоя в выходной файл XML. Вот мои ожидаемые результаты XML. Есть ли простой способ сделать это? Я не уверен, что NestingLevel может помочь сделать это. Я хочу найти простой способ, который не меняет структуру MyClass и MyObject.

Ожидаемый результат сериализации XML,

<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <MyObjectProperty>
    <AdditionalLayer1>
      <AdditionalLayer2>
        <ObjectName>Foo</ObjectName>
      </AdditionalLayer1>
    </AdditionalLayer2>
  </MyObjectProperty>
</MyClass>

Текущий результат сериализации XML,

<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <MyObjectProperty>
    <ObjectName>Foo</ObjectName>
  </MyObjectProperty>
</MyClass>

Мой текущий код,

public class MyClass
{
    public MyObject MyObjectProperty;
}
public class MyObject
{
    public string ObjectName;
}

public class Program
{
    static void Main(string[] args)
    {
        XmlSerializer s = new XmlSerializer(typeof(MyClass));
        FileStream fs = new FileStream("foo.xml", FileMode.Create);
        MyClass instance = new MyClass();
        instance.MyObjectProperty = new MyObject();
        instance.MyObjectProperty.ObjectName = "Foo";
        s.Serialize(fs, instance);

        return;
    }
}

Ответы [ 5 ]

5 голосов
/ 04 августа 2009

Я хочу найти простой способ, который не меняет структуру MyClass и MyObject.

Честно говоря, этого не произойдет.XmlSerializer (при простом использовании) следует структуре классов / членов.Таким образом, вы не можете добавлять дополнительные слои без изменения структуры.

При использовании по индивидуальному заказу (IXmlSerializable), единственное, что вы можете сказать наверняка, это то, что это не просто ... этоЭто не забавный интерфейс для реализации.

Мой совет: представьте DTO, который имитирует желаемый формат, и ознакомьтесь с ним перед сериализацией.

4 голосов
/ 04 августа 2009

Зачем вам нужны эти два дополнительных слоя?

Это бизнес-требование, вы должны добавить эти два объекта в вашу объектную модель:

public class MyClass
{
    public AdditionalLayer1 AdditionalLayer1;
}
public class AdditionalLayer1
{
    public AdditionalLayer2 AdditionalLayer2;
}
public class AdditionalLayer2
{
    public MyObject MyObjectProperty;
}
public class MyObject
{
    public string ObjectName;
}

если это просто из-за некоторых требований совместимости, вы можете либо выполнить вышеуказанное, либо реализовать IXmlSerializable на MyClass:

public class MyClass : IXmlSerializable
{
    public MyObject MyObjectProperty;

    public void WriteXml (XmlWriter writer)
    {
        //open the two layers
        //serialize MyObject
        //close the two layers
    }

    public void ReadXml (XmlReader reader)
    {
        //read all the layers back, etc
    }

    public XmlSchema GetSchema()
    {
        return(null);
    }

}
2 голосов
/ 04 августа 2009

Вы можете выполнить преобразование с помощью XSL после сериализации и добавить «отсутствующие» теги.

1 голос
/ 04 августа 2009

Я бы предложил сериализовать в MemoryStream вместо FileStream, а затем загрузить XML в XmlDocument, а затем использовать методы этого класса для вставки дополнительных узлов, которые вы хотите. После этого вы можете сохранить его.

0 голосов
/ 25 августа 2009

Я сделал это совсем недавно и не нашел переопределения интерфейса IXmlSerializable вообще сложным или сложным. Сериализация / десериализация как обычно, но для класса, который содержит подкласс, который необходимо обернуть в дополнительные теги, производные от IXmlSerializable:

class ContainingClass : IXmlSerializable
{
 ...

#region IXmlSerializable Members

public XmlSchema GetSchema()
{
  return null;
}

public void ReadXml(XmlReader reader)
{
  **reader.ReadStartElement("Equipment");**

  XmlSerializer ser = new XmlSerializer(typeof(Host));

  while (reader.NodeType != XmlNodeType.EndElement)
  {
    Host newHost = new Host();
    newHost.Name = (string) ser.Deserialize(reader);
    _hosts.Add(newHost);

    reader.Read();
  }

  // Read the node to its end.
  // Next call of the reader methods will crash if not called.
  **reader.ReadEndElement(); // "Equipment"**
}

public void WriteXml(XmlWriter writer)
{
  XmlSerializer ser = new XmlSerializer(typeof(Host));
  **writer.WriteStartElement("Equipment");**
  foreach (Host host in this._hosts)
  {
    ser.Serialize(writer, host);
  }
  **writer.WriteEndElement();**
}

#endregion

Все, что я здесь делаю, - это завершение де / сериализации объектов более низкого уровня. Здесь я оборачиваю дополнительный тег «Снаряжение» вокруг всех Хозяев в коллекции этого класса. Здесь вы можете добавить столько тегов, сколько захотите, если закроете каждый из них, который начинаете.

ПРИМЕЧАНИЕ. Жирным шрифтом отображается ** текст ** - просто убедитесь, что вы избавились от двойных звездочек:)

...