.NET XML序列化

问题描述:

我想序列化和反序列化混合数据转换成XML。经过一番搜索我发现有这样做的方法有两种: System.Runtime.Serialization.Formatters.Soap.SoapFormatter System.Xml.Serialization.XmlSerializer 的。然而,无论是横空出世,以满足我的要求,因为:

I would like to serialize and deserialize mixed data into XML. After some searches I found out that there were two ways of doing it: System.Runtime.Serialization.Formatters.Soap.SoapFormatter and System.Xml.Serialization.XmlSerializer. However, neither turned out to match my requirements, since:

  • 在SoapFormatter不支持泛型类型的序列
  • XmlSerializer的拒绝序列化实施的的IDictionary 的类型,更何况它远远不容易使用的不是正常的序列化(如的看到此等问题
  • SoapFormatter doesn't support serialization of generic types
  • XmlSerializer refuses to serialize types that implement IDictionary, not to mention that it's far less easy-to-use than "normal" serialization (e.g. see this SO question)

我不知道是否存在不具有这些限制的实现?我发现的尝试(例如 CustomXmlSerializer 和的 YAXLib 作为一个related SO质疑),但他们似乎并没有擦出火花。

I'm wondering if there exists an implementation that doesn't have these limitations? I have found attempts (for example CustomXmlSerializer and YAXLib as suggested in a related SO question), but they don't seem to work either.

我在想写作等串行自己(虽然它的确似乎不是很容易的事),但后来我发现自己受了CLR,因为我无法创建类型赢得对象实例'T有paramaterless构造,即使我使用反射。我记得读过的地方,在System.Runtime.Serialization实施反序列化对象时莫名其妙地绕过正常的对象的创建机制,虽然我不知道。如何任何提示可以这样做吗?击>
(请参阅编辑#3)

I was thinking about writing such serializer myself (though it certainly doesn't seem to be a very easy task), but then I find myself limited by the CLR, as I cannot create object instances of types that won't have a paramaterless constructor, even if I'm using reflection. I recall having read somewhere that implementations in System.Runtime.Serialization somehow bypass the normal object creation mechanism when deserializing objects, though I'm not sure. Any hints of how could this be done?
(See edit #3)

可能有人请点我正确的方向呢?

Could somebody please point me to the right direction with this?

修改:我使用.NET 3.5 SP1

Edit: I'm using .NET 3.5 SP1.

编辑#2 :只是要清楚,我想一个解决方案,那就是尽可能多喜欢使用BinaryFormatter的可能,这意味着它应该需要尽可能少的额外的code和注解

Edit #2: Just to be clear, I'd like a solution that is as much like using BinaryFormatter as possible, meaning that it should require the least possible extra code and annotations.

编辑#3 :有一些额外的谷歌搜索,我发现了一个.NET类名为 System.Runtime.Serialization.FormatterServices.GetUninitializedObject ,实际上可以返回归零指定类型,这是在反序列化很大的帮助(如果我要实现它自己)的对象。我还是想找到一个现有的解决方案,但。

Edit #3: with some extra Googling, I found a .NET class called System.Runtime.Serialization.FormatterServices.GetUninitializedObject that actually can return "zeroed" objects of a specified type, which is great help in deserialization (if I get to implement it myself). I'd still like to find an existing solution though.

根据您的.NET版本和您的数据的复杂性,您可以使用LINQ to XML序列化抱有侥幸心理:

Depending on your .NET version and the complexity of your data, you may have luck using LINQ to XML to serialize:

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
                                    })
               };
}