.NET XML сериализация - PullRequest
       28

.NET XML сериализация

1 голос
/ 01 января 2011

Я хотел бы сериализовать и десериализовать смешанные данные в XML. После некоторых поисков я обнаружил, что есть два способа сделать это: System.Runtime.Serialization.Formatters.Soap.SoapFormatter и System.Xml.Serialization.XmlSerializer . Однако ни один из них не соответствует моим требованиям, поскольку:

  • SoapFormatter не поддерживает сериализацию универсальных типов
  • XmlSerializer отказывается сериализовать типы, которые реализуют IDictionary , не говоря уже о том, что он гораздо менее прост в использовании, чем "обычная" сериализация (например, см. Этот вопрос SO )

Мне интересно, существует ли реализация, которая не имеет этих ограничений? Я нашел попытки (например, CustomXmlSerializer и YAXLib , как предложено в связанном вопросе SO ), но, похоже, они тоже не работают.

Я думал о написании такого сериализатора самостоятельно (хотя это, конечно, не кажется очень легкой задачей), но потом я обнаружил, что ограничен CLR, так как не могу создавать экземпляры объектов типов, которые выиграли У меня нет конструктора без параметров, даже если я использую отражение. Я помню, что где-то читал, что реализации в System.Runtime.Serialization каким-то образом обходят обычный механизм создания объектов при десериализации объектов , хотя я не уверен. Любые намеки на то, как это можно сделать?
(См. Редакцию № 3)

Может кто-нибудь, пожалуйста, указать мне правильное направление с этим?

Редактировать : Я использую .NET 3.5 SP1.

Редактировать # 2 : Просто чтобы прояснить ситуацию, я бы хотел, чтобы решение, максимально приближенное к использованию BinaryFormatter, означало бы, что для него потребуется как можно меньше дополнительного кода и аннотаций.

Edit # 3 : с некоторым дополнительным поиском в Google я нашел класс .NET с именем System.Runtime.Serialization.FormatterServices.GetUninitializedObject , который фактически может возвращать "обнуленные" объекты объекта. указанный тип, который отлично помогает в десериализации (если я получу это реализовать самостоятельно). Я все же хотел бы найти существующее решение.

Ответы [ 5 ]

3 голосов
/ 01 января 2011

Я имел большой успех, используя класс datacontractserializer.

Вот очень хорошая статья, сравнивающая сериализаторы ссылка

2 голосов
/ 01 января 2011

В зависимости от версии .NET и сложности ваших данных вам может повезти, если использовать LINQ to XML для сериализации:

internal class Inner
{
    public int Number { get; set; }
    public string NotNumber { get; set; }
}

internal class Outer
{
    public int ID { get; set; }
    public Dictionary<string, Inner> Dict { get; set; }
}

internal class Program
{
    private static void Main()
    {
        var data = new Outer
                       {
                           ID = 1,
                           Dict =
                               new Dictionary<string, Inner>
                                   {
                                       {
                                           "ABC",
                                           new Inner
                                               {
                                                   Number = 1,
                                                   NotNumber = "ABC1"
                                               }
                                           },
                                       {
                                           "DEF",
                                           new Inner
                                               {
                                                   Number = 2,
                                                   NotNumber = "DEF2"
                                               }
                                           }
                                   }
                       };

        var serialized =
            new XDocument(new XElement("Outer",
                                       new XAttribute("id", data.ID),
                                       new XElement("Dict",
                                                    from i in data.Dict
                                                    select
                                                        new XElement(
                                                        "Entry",
                                                        new XAttribute(
                                                            "key", i.Key),
                                                        new XAttribute(
                                                            "number",
                                                            i.Value.Number),
                                                        new XAttribute(
                                                            "notNumber",
                                                            i.Value.
                                                                NotNumber)))));

        Console.WriteLine(serialized);
        Console.Write("ENTER to finish: ");
        Console.ReadLine();
    }
}

Результат:

<Outer id="1">
  <Dict>
    <Entry key="ABC" number="1" notNumber="ABC1" />
    <Entry key="DEF" number="2" notNumber="DEF2" />
  </Dict>
</Outer>

десериализация:

private static Outer Deserialize(XDocument serialized)
{
    if (serialized.Root == null)
    {
        return null;
    }

    var outerElement = serialized.Root.Element("Outer");
    if (outerElement == null)
    {
        return null;
    }

    return new Outer
               {
                   ID =
                       int.Parse(
                           outerElement.Attribute("id").Value),
                   Dict =
                       outerElement.Element("Dict").
                           Elements("Entry").ToDictionary(
                               k => k.Attribute("key").Value,
                               v => new Inner
                                    {
                                       Number = Convert.ToInt32(v.Attribute("number").Value),
                                       NotNumber = v.Attribute("notNumber").Value
                                    })
               };
}
2 голосов
/ 01 января 2011

Какую версию .NET Framework вы используете?Если вы используете .NET 3.0 или выше, вам может повезти с DataContractSerializer или NetDataContractSerializer .Оба они сериализуются в XML, но работают совершенно иначе, чем XmlSerializer.

1 голос
/ 01 января 2011

Реализация пользовательской сериализации XML не так уж плоха. Вы можете реализовать IXmlSerializable в классе, который обычный XmlSerializer не может поддерживать по умолчанию.

Эта статья CodeProject содержит хорошее объяснение IXmlSerializable, а в этом блоге дает другой взгляд на более или менее ту же вещь.

0 голосов
/ 01 января 2011

Я предлагаю DataContractJsonSerializer, который дает более короткий вывод и лучше обрабатывает словари.

...