65.9K
CodeProject 正在变化。 阅读更多。
Home

适用于 .NET 的扩展 XML 序列化器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (26投票s)

2016 年 8 月 31 日

MIT

7分钟阅读

viewsIcon

69194

downloadIcon

2444

适用于 .NET 4 和 .NET CORE 的扩展 XML 序列化器,支持 WebApi 和 ASP Core 集成。

引言

适用于 .NET 4 和 .NET CORE 的扩展 XML 序列化器。 ExtendedXmlSerializer

支持平台

  • .NET 4.5
  • .NET Platform Standard 1.6

支持功能

  • 反序列化标准 XMLSerializer 的 xml
  • 序列化类、结构体、泛型类、原始类型、泛型列表和字典、数组、枚举
  • 序列化带有属性接口的类
  • 序列化循环引用和引用 ID
  • 反序列化旧版本 xml
  • 属性加密
  • 自定义序列化器
  • 支持 XmlElementAttributeXmlRootAttribute
  • POCO - 所有配置(迁移、自定义序列化器...)都位于类之外

标准 .NET XML 序列化器功能非常有限

  • 不支持带有循环引用或接口属性的类的序列化。
  • 没有读取旧版本 XML 的机制。
  • 不支持用接口类型定义的属性。
  • 不支持只读集合属性(如 Xaml 所支持的)。
  • 不支持带参数的构造函数。
  • 不支持私有构造函数。
  • 如果您想创建自定义序列化器,您的类必须继承自 IXmlSerializable。这意味着您的类将不是 POCO 类。
  • 不支持 IoC

基础知识

ExtendedXmlSerializer 中,一切都始于一个配置容器,您可以使用它来配置序列化器并最终创建它。

    var serializer = new ConfigurationContainer()
                                                // Configure...
                                                .Create();

使用这个简单的示例类

    public sealed class Subject
    {
        public string Message { get; set; }
    
        public int Count { get; set; }
    }

默认序列化器的结果如下所示

    <?xml version="1.0" encoding="utf-8"?>
    <Subject xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Introduction;assembly=ExtendedXmlSerializer.Samples">
      <Message>Hello World!</Message>
      <Count>6776</Count>
    </Subject>

我们可以更进一步,通过配置 Subject 的 Type 和 Member 属性来影响其 Xml 的生成方式。以下示例将 Subject 的名称配置为生成 ModifiedSubject

    var serializer = new ConfigurationContainer().ConfigureType<Subject>()
                                                 .Name("ModifiedSubject")
                                                 .Create();
    <?xml version="1.0" encoding="utf-8"?>
    <ModifiedSubject xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Introduction;assembly=ExtendedXmlSerializer.Samples">
      <Message>Hello World!</Message>
      <Count>6776</Count>
    </ModifiedSubject>

进一步深入,我们还可以配置类型的成员信息。例如,将 Subject.Message 配置为生成 Text 而不是原来的名字

    var serializer = new ConfigurationContainer().ConfigureType<Subject>()
                                                 .Member(x => x.Message)
                                                 .Name("Text")
                                                 .Create();
    <?xml version="1.0" encoding="utf-8"?>
    <Subject xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Introduction;assembly=ExtendedXmlSerializer.Samples">
      <Text>Hello World!</Text>
      <Count>6776</Count>
    </Subject>

Xml 设置

如果您想通过 XmlWriterSettingsXmlReaderSettings 分别配置 XML 的写入和读取设置,您可以通过我们创建的扩展方法来实现。

    var subject = new Subject{ Count = 6776, Message = "Hello World!" };
    var serializer = new ConfigurationContainer().Create();
    var contents = serializer.Serialize(new XmlWriterSettings {Indent = true}, subject);
    // ...

以及用于读取的设置

    var instance = serializer.Deserialize<Subject>(new XmlReaderSettings{IgnoreWhitespace = false}, contents);
    // ...

序列化

现在您的配置容器已经配置完成,并且序列化器也已创建,是时候开始序列化了。

    var serializer = new ConfigurationContainer().Create();
    var obj = new TestClass();
    var xml = serializer.Serialize(obj);

反序列化

    var obj2 = serializer.Deserialize<TestClass>(xml);

Fluent API

ExtendedXmlSerializer 使用流式 API 进行配置。示例

    var serializer = new ConfigurationContainer()
        .UseEncryptionAlgorithm(new CustomEncryption())
        .Type<Person>() // Configuration of Person class
            .Member(p => p.Password) // First member
                .Name("P")
                .Encrypt()
            .Member(p => p.Name) // Second member
                .Name("T")
        .Type<TestClass>() // Configuration of another class
            .CustomSerializer(new TestClassSerializer())
        .Create();

字典的序列化

您可以序列化任何类型的泛型字典。

    public class TestClass
    {
        public Dictionary<int, string> Dictionary { get; set; }
    }
    var obj = new TestClass
    {
        Dictionary = new Dictionary<int, string>
        {
            {1, "First"},
            {2, "Second"},
            {3, "Other"},
        }
    };

输出的 XML 将会是这样

    <?xml version="1.0" encoding="utf-8"?>
    <TestClass xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Dictianary;assembly=ExtendedXmlSerializer.Samples">
      <Dictionary>
        <Item xmlns="https://extendedxmlserializer.github.io/system">
          <Key>1</Key>
          <Value>First</Value>
        </Item>
        <Item xmlns="https://extendedxmlserializer.github.io/system">
          <Key>2</Key>
          <Value>Second</Value>
        </Item>
        <Item xmlns="https://extendedxmlserializer.github.io/system">
          <Key>3</Key>
          <Value>Other</Value>
        </Item>
      </Dictionary>
    </TestClass>

如果您使用 UseOptimizedNamespaces 函数,xml 将会是这样

    <?xml version="1.0" encoding="utf-8"?>
    <TestClass xmlns:sys="https://extendedxmlserializer.github.io/system" xmlns:exs="https://extendedxmlserializer.github.io/v2" xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Dictianary;assembly=ExtendedXmlSerializer.Samples">
      <Dictionary>
        <sys:Item>
          <Key>1</Key>
          <Value>First</Value>
        </sys:Item>
        <sys:Item>
          <Key>2</Key>
          <Value>Second</Value>
        </sys:Item>
        <sys:Item>
          <Key>3</Key>
          <Value>Other</Value>
        </sys:Item>
      </Dictionary>
    </TestClass>

自定义序列化

如果您的类需要以非标准方式进行序列化

    public class TestClass
    {
        public TestClass(string paramStr, int paramInt)
        {
            PropStr = paramStr;
            PropInt = paramInt;
        }
    
        public string PropStr { get; private set; }
        public int PropInt { get; private set; }
    }

您必须创建自定义序列化器

    public class TestClassSerializer : IExtendedXmlCustomSerializer<TestClass>
    {
        public TestClass Deserialize(XElement element)
        {
            var xElement = element.Member("String");
            var xElement1 = element.Member("Int");
            if (xElement != null && xElement1 != null)
            {
                var strValue = xElement.Value;
    
                var intValue = Convert.ToInt32(xElement1.Value);
                return new TestClass(strValue, intValue);
            }
            throw new InvalidOperationException("Invalid xml for class TestClassWithSerializer");
        }
    
        public void Serializer(XmlWriter writer, TestClass obj)
        {
            writer.WriteElementString("String", obj.PropStr);
            writer.WriteElementString("Int", obj.PropInt.ToString(CultureInfo.InvariantCulture));
        }
    }

然后,您必须将自定义序列化器添加到 TestClass 的配置中

    var serializer = new ConfigurationContainer().Type<TestClass>()
                                                 .CustomSerializer(new TestClassSerializer())
                                                 .Create();

反序列化旧版本 xml

在标准的 XMLSerializer 中,如果您更改了模型,就无法反序列化 XML。在 ExtendedXMLSerializer 中,您可以为每个类单独创建迁移器。例如:如果您有一个大类,它使用了小类,而这个小类被更改了,您可以只为这个小类创建一个迁移器。您无需修改整个大 XML。现在我将向您展示一个简单的例子

如果您有一个类

    public class TestClass
    {
        public int Id { get; set; }
        public string Type { get; set; }
    }

生成的 XML 如下所示

    <? xml version="1.0" encoding="utf-8"?>
    <TestClass xmlns="clr-namespace:ExtendedXmlSerialization.Samples.MigrationMap;assembly=ExtendedXmlSerializer.Samples">
      <Id>1</Id>
      <Type>Type</Type>
    </TestClass>

然后您重命名了属性

    public class TestClass
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

生成的 XML 如下所示

    <? xml version="1.0" encoding="utf-8"?>
    <TestClass xmlns:exs="https://extendedxmlserializer.github.io/v2" exs:version="1" xmlns="clr-namespace:ExtendedXmlSerialization.Samples.MigrationMap;assembly=ExtendedXmlSerializer.Samples">
      <Id>1</Id>
      <Name>Type</Name>
    </TestClass>

然后,您添加了一个新属性,并且想在反序列化时计算新值。

    public class TestClass
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Value { get; set; }
    }

新的 XML 应该看起来像这样

    <?xml version="1.0" encoding="utf-8"?>
    <TestClass xmlns:exs="https://extendedxmlserializer.github.io/v2" exs:version="2" xmlns="clr-namespace:ExtendedXmlSerializer.Samples.MigrationMap;assembly=ExtendedXmlSerializer.Samples">
      <Id>1</Id>
      <Name>Type</Name>
      <Value>Calculated</Value>
    </TestClass>

您可以使用迁移来迁移(读取)旧版本的 XML

    public class TestClassMigrations : IEnumerable<Action<XElement>>
    {
        public static void MigrationV0(XElement node)
        {
            var typeElement = node.Member("Type");
            // Add new node
            node.Add(new XElement("Name", typeElement.Value));
            // Remove old node
            typeElement.Remove();
        }
    
        public static void MigrationV1(XElement node)
        {
            // Add new node
            node.Add(new XElement("Value", "Calculated"));
        }
    
        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    
        public IEnumerator<Action<XElement>> GetEnumerator()
        {
            yield return MigrationV0;
            yield return MigrationV1;
        }
    }

然后,您必须在配置中注册您的 TestClassMigrations

    var serializer = new ConfigurationContainer().ConfigureType<TestClass>()
                                                 .AddMigration(new TestClassMigrations())
                                                 .Create();

可扩展性

在完成了类型和成员配置之后,我们可以将注意力转移到真正让 ExtendedXmlSeralizer 运转起来的关键:可扩展性。顾名思义,ExtendedXmlSeralizer 提供了一个非常灵活(但毕竟是新的)的扩展模型,您可以在此基础上构建自己的扩展。您在 ExtendedXmlSeralizer 中遇到的几乎所有功能都是通过扩展实现的。本文档的其余部分将展示 ExtendedXmlSerializer 通过其扩展系统实现的主要功能。

 

对象引用和循环引用

如果您有一个类

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
    
        public Person Boss { get; set; }
    }
    
    public class Company
    {
        public List<Person> Employees { get; set; }
    }

然后您创建了一个具有循环引用的对象,如下所示

    var boss = new Person {Id = 1, Name = "John"};
    boss.Boss = boss; //himself boss
    var worker = new Person {Id = 2, Name = "Oliver"};
    worker.Boss = boss;
    var obj = new Company
    {
        Employees = new List<Person>
        {
            worker,
            boss
        }
    };

您必须将 Person 类配置为引用对象

    var serializer = new ConfigurationContainer().ConfigureType<Person>()
                                                 .EnableReferences(p => p.Id)
                                                 .Create();

输出的 XML 将会是这样

    <?xml version="1.0" encoding="utf-8"?>
    <Company xmlns="clr-namespace:ExtendedXmlSerializer.Samples.ObjectReference;assembly=ExtendedXmlSerializer.Samples">
      <Employees>
        <Capacity>4</Capacity>
        <Person Id="2">
          <Name>Oliver</Name>
          <Boss Id="1">
            <Name>John</Name>
            <Boss xmlns:exs="https://extendedxmlserializer.github.io/v2" exs:entity="1" />
          </Boss>
        </Person>
        <Person xmlns:exs="https://extendedxmlserializer.github.io/v2" exs:entity="1" />
      </Employees>
    </Company>

属性加密

如果您有一个属性需要加密的类

    public class Person
    {
        public string Name { get; set; }
        public string Password { get; set; }
    }

您必须实现 IEncryption 接口。例如,这里将展示 Base64 编码,但在实际应用中最好使用更安全的方式,例如 RSA。

    public class CustomEncryption : IEncryption
    {
        public string Parse(string data)
            => Encoding.UTF8.GetString(Convert.FromBase64String(data));
    
        public string Format(string instance)
            => Convert.ToBase64String(Encoding.UTF8.GetBytes(instance));
    }

然后,您需要指定哪些属性将被加密,并注册您的 IEncryption 实现。

    var serializer = new ConfigurationContainer().UseEncryptionAlgorithm(new CustomEncryption())
                                                 .ConfigureType<Person>()
                                                 .Member(p => p.Password)
                                                 .Encrypt()
                                                 .Create();

自定义转换

ExtendedXmlSerializer 在组合和分解对象方面做得相当不错(如果我们自己说的话),但如果您有一个类型需要以特定方式进行序列化,并且该类型可以被分解为一个 string,那么您可以为其注册一个自定义转换器。

 

使用以下代码

    public sealed class CustomStructConverter : IConverter<CustomStruct>
    {
        public static CustomStructConverter Default { get; } = new CustomStructConverter();
        CustomStructConverter() {}
    
        public bool IsSatisfiedBy(TypeInfo parameter) => typeof(CustomStruct).GetTypeInfo()
                                                                             .IsAssignableFrom(parameter);
    
        public CustomStruct Parse(string data) =>
            int.TryParse(data, out var number) ? new CustomStruct(number) : CustomStruct.Default;
    
        public string Format(CustomStruct instance) => instance.Number.ToString();
    }
    
    public struct CustomStruct
    {
        public static CustomStruct Default { get; } = new CustomStruct(6776);
    
        public CustomStruct(int number)
        {
            Number = number;
        }
        public int Number { get; }
    }

注册转换器

    var serializer = new ConfigurationContainer().Register(CustomStructConverter.Default).Create();
    var subject = new CustomStruct(123);
    var contents = serializer.Serialize(subject);
    // ...
    <?xml version="1.0" encoding="utf-8"?>
    <CustomStruct xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples">123</CustomStruct>

优化命名空间

默认情况下,Xml 命名空间是“按需”生成的

    <?xml version="1.0" encoding="utf-8"?>
    <List xmlns:exs="https://extendedxmlserializer.github.io/v2" exs:arguments="Object" xmlns="https://extendedxmlserializer.github.io/system">
      <Capacity>4</Capacity>
      <Subject xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples">
        <Message>First</Message>
      </Subject>
      <Subject xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples">
        <Message>Second</Message>
      </Subject>
      <Subject xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples">
        <Message>Third</Message>
      </Subject>
    </List>

但只需一次调用 UseOptimizedNamespaces,命名空间就会放在文档的根部,从而减小文档的大小。

    var serializer = new ConfigurationContainer().UseOptimizedNamespaces()
                                                 .Create();
    var subject = new List<object>
                    {
                        new Subject {Message = "First"},
                        new Subject {Message = "Second"},
                        new Subject {Message = "Third"}
                    };
    var contents = serializer.Serialize(subject);
    // ...
    <?xml version="1.0" encoding="utf-8"?>
    <List xmlns:ns1="clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples" xmlns:exs="https://extendedxmlserializer.github.io/v2" exs:arguments="Object" xmlns="https://extendedxmlserializer.github.io/system">
      <Capacity>4</Capacity>
      <ns1:Subject>
        <Message>First</Message>
      </ns1:Subject>
      <ns1:Subject>
        <Message>Second</Message>
      </ns1:Subject>
      <ns1:Subject>
        <Message>Third</Message>
      </ns1:Subject>
    </List>

隐式命名空间/类型

如果您根本不喜欢命名空间,您可以注册类型,使其在渲染到文档时不会生成命名空间。

    var serializer = new ConfigurationContainer().EnableImplicitTyping(typeof(Subject))
                                                 .Create();
    var subject = new Subject{ Message = "Hello World!  No namespaces, yay!" };
    var contents = serializer.Serialize(subject);
    // ...
    <?xml version="1.0" encoding="utf-8"?>
    <Subject>
      <Message>Hello World!  No namespaces, yay!</Message>
    </Subject>

自动格式化(属性)

在 XML 文档中生成数据的默认行为是使用元素,这可能会有点冗长和啰嗦。

    var serializer = new ConfigurationContainer().UseOptimizedNamespaces()
                                                 .Create();
    var subject = new List<object>
                    {
                        new Subject {Message = "First"},
                        new Subject {Message = "Second"},
                        new Subject {Message = "Third"}
                    };
    var contents = serializer.Serialize(subject);
    // ...
    <?xml version="1.0" encoding="utf-8"?>
    <SubjectWithThreeProperties xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples">
      <Number>123</Number>
      <Message>Hello World!</Message>
      <Time>2017-11-21T10:55:38.0990077+01:00</Time>
    </SubjectWithThreeProperties>

使用 UseAutoFormatting 调用将启用所有已注册 IConverter(转换为字符串和反之)的类型以属性形式生成。

    <?xml version="1.0" encoding="utf-8"?>
    <SubjectWithThreeProperties Number="123" Message="Hello World!" Time="2017-11-21T10:55:38.0990077+01:00" xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples" />

私有构造函数

经典 XmlSerializer 的一个限制是它不支持私有构造函数,但 ExtendedXmlSerializer 通过其 EnableAllConstructors 调用支持这一点。

    public sealed class SubjectByFactory
    {
        public static SubjectByFactory Create(string message) => new SubjectByFactory(message);
    
        SubjectByFactory() : this(null) {} // Used by serializer.
    
        SubjectByFactory(string message) => Message = message;
    
        public string Message { get; set; }
    }
    var serializer = new ConfigurationContainer().EnableAllConstructors()
                                                 .Create();
    var subject = SubjectByFactory.Create("Hello World!");
    var contents = serializer.Serialize(subject);
    // ...
    <?xml version="1.0" encoding="utf-8"?>
    <SubjectByFactory xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples">
      <Message>Hello World!</Message>
    </SubjectByFactory>

带参数的成员和内容

将这个概念进一步延伸,就得到了 ExtendedXmlSerlializer 中我们最喜欢的一个功能。经典序列化器只支持无参公共构造函数。使用 ExtendedXmlSerializer,您可以使用 EnableParameterizedContent 调用来启用构造函数中的带参数参数,这些参数按照约定命名方式与它们要赋值的属性同名。

    public sealed class ParameterizedSubject
    {
        public ParameterizedSubject(string message, int number, DateTime time)
        {
            Message = message;
            Number = number;
            Time = time;
        }
    
        public string Message { get; }
        public int Number { get; }
        public DateTime Time { get; }
    }
    var serializer = new ConfigurationContainer().EnableParameterizedContent()
                                                 .Create();
    var subject = new ParameterizedSubject("Hello World!", 123, DateTime.Now);
    var contents = serializer.Serialize(subject);
    // ...
    <?xml version="1.0" encoding="utf-8"?>
    <ParameterizedSubject xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples">
      <Message>Hello World!</Message>
      <Number>123</Number>
      <Time>2017-11-21T10:55:38.3180296+01:00</Time>
    </ParameterizedSubject>

元组

通过启用带参数内容,可以实现许多可能性,例如序列化 Tuples。当然,可序列化的 Tuples 最近才在最新版本的 C# 中引入。在这里,您可以将其与我们的成员命名功能结合起来,为您的 tuple 属性提供更好的命名。

    var serializer = new ConfigurationContainer().EnableParameterizedContent()
                                                 .Type<Tuple<string>>()
                                                 .Member(x => x.Item1)
                                                 .Name("Message")
                                                 .Create();
    var subject = Tuple.Create("Hello World!");
    var contents = serializer.Serialize(subject);
    // ...
    <?xml version="1.0" encoding="utf-8"?>
    <Tuple xmlns:exs="https://extendedxmlserializer.github.io/v2" exs:arguments="string" xmlns="https://extendedxmlserializer.github.io/system">
      <Message>Hello World!</Message>
    </Tuple>

实验性 Xaml 特性:附加属性

在 v2 版本中,我们对 ExtendedXmlSerializer 做了一些有趣的改进,增加了对序列化对象图中的对象附加属性的支持。但我们并没有将其限制在继承自 DependencyObject 的对象上,*所有* 对象都可以从中受益。看看这个

        sealed class NameProperty : ReferenceProperty<Subject, string>
        {
            public const string DefaultMessage = "The Name Has Not Been Set";
    
            public static NameProperty Default { get; } = new NameProperty();
            NameProperty() : base(() => Default, x => DefaultMessage) {}
        }
    
        sealed class NumberProperty : StructureProperty<Subject, int>
        {
            public const int DefaultValue = 123;
    
            public static NumberProperty Default { get; } = new NumberProperty();
            NumberProperty() : base(() => Default, x => DefaultValue) {}
        }
    
    var serializer = new ConfigurationContainer().EnableAttachedProperties(NameProperty.Default,
                                                                           NumberProperty.Default)
                                                 .Create();
    var subject = new Subject {Message = "Hello World!"};
    subject.Set(NameProperty.Default, "Hello World from Attached Properties!");
    subject.Set(NumberProperty.Default, 123);
    
    var contents = serializer.Serialize(subject);
    // ...
    <?xml version="1.0" encoding="utf-8"?>
    <Subject xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples">
      <Message>Hello World!</Message>
      <NameProperty.Default>Hello World from Attached Properties!</NameProperty.Default>
      <NumberProperty.Default>123</NumberProperty.Default>
    </Subject>

(请注意,此功能是实验性的,但请尝试使用并告诉我们您的想法!)

 

实验性 Xaml 特性:标记扩展

将最棒的功能留到最后,我们对 Xaml 最重要的功能之一——标记扩展——提供了实验性支持。

    sealed class Extension : IMarkupExtension
    {
        const string Message = "Hello World from Markup Extension! Your message is: ", None = "N/A";
    
        readonly string _message;
    
        public Extension() : this(None) {}
    
        public Extension(string message)
        {
            _message = message;
        }
    
        public object ProvideValue(IServiceProvider serviceProvider) => string.Concat(Message, _message);
    }
    var contents =
        @"<?xml version=""1.0"" encoding=""utf-8""?>
            <Subject xmlns=""clr-namespace:ExtendedXmlSerializer.Samples.Extensibility;assembly=ExtendedXmlSerializer.Samples""
            Message=""{Extension 'PRETTY COOL HUH!!!'}"" />";
    var serializer = new ConfigurationContainer().EnableMarkupExtensions()
                                                 .Create();
    var subject = serializer.Deserialize<Subject>(contents);
    Console.WriteLine(subject.Message); // "Hello World from Markup Extension! Your message is: PRETTY COOL HUH!!!"

(请注意,此功能是实验性的,但请尝试使用并告诉我们您的想法!)

 

如何从 v1.x 升级到 v2

最后,如果您有 v1 的文档,您需要将它们升级到 v2 才能工作。这包括在 v1 序列化器的实例中读取文档,然后在 v2 序列化器的实例中写入。我们提供了 ExtendedXmlSerializer.Legacy nuget 包来协助完成此目标。

    <?xml version="1.0" encoding="utf-8"?><ArrayOfSubject><Subject type="ExtendedXmlSerializer.Samples.Introduction.Subject"><Message>First</Message><Count>0</Count></Subject><Subject type="ExtendedXmlSerializer.Samples.Introduction.Subject"><Message>Second</Message><Count>0</Count></Subject><Subject type="ExtendedXmlSerializer.Samples.Introduction.Subject"><Message>Third</Message><Count>0</Count></Subject></ArrayOfSubject>
    var legacySerializer = new ExtendedXmlSerialization.ExtendedXmlSerializer();
    var content = File.ReadAllText(@"bin\Upgrade.Example.v1.xml"); // Path to your legacy xml file.
    var subject = legacySerializer.Deserialize<List<Subject>>(content);
    
    // Upgrade:
    var serializer = new ConfigurationContainer().Create();
    var contents = serializer.Serialize(new XmlWriterSettings {Indent = true}, subject);
    File.WriteAllText(@"bin\Upgrade.Example.v2.xml", contents);
    // ...
    <?xml version="1.0" encoding="utf-8"?>
    <List xmlns:ns1="clr-namespace:ExtendedXmlSerializer.Samples.Introduction;assembly=ExtendedXmlSerializer.Samples" xmlns:exs="https://extendedxmlserializer.github.io/v2" exs:arguments="ns1:Subject" xmlns="https://extendedxmlserializer.github.io/system">
      <Capacity>4</Capacity>
      <ns1:Subject>
        <Message>First</Message>
        <Count>0</Count>
      </ns1:Subject>
      <ns1:Subject>
        <Message>Second</Message>
        <Count>0</Count>
      </ns1:Subject>
      <ns1:Subject>
        <Message>Third</Message>
        <Count>0</Count>
      </ns1:Subject>
    </List>

历史

  • 2017-11-14 - v2.0.0 - 重写版本,包含许多新功能。
  • 2016-12-06 - v1.5.0
    • 支持没有 set 访问器的集合属性。
    • 支持 IDictionaryIListISet 属性。
    • 属性类型仅在必要时添加。
  • 2016-11-18 - v1.4.1 - 支持排序参数和修复 Object 属性的序列化
  • 2016-11-15 - v1.4.0 - 支持 XmlElementAttributeXmlRootAttribute
  • 2016-10-18 - v1.3.0 - 属性加密
  • 2016-09-22 - v1.2.0 - 支持 Dictionary<TKey, TSource>
  • 2016-09-14 - v1.1.0 - 与 ASP.NET Core 和 WebApi 集成
  • 2016-08-31 - v1.0.0 - 第一个版本

贡献者

© . All rights reserved.