C#:如何通过XmlSerializer直接序列化列表生成指定派生类元素XML
直接序列化
List<Bar>生成自定义元素名的XML方案 好问题!要实现直接序列化List<Bar>时生成和方法A一致的XML(也就是每个派生类对应<derived1>、<derived2>这类自定义元素名,而非带xsi:type的<base>),你可以通过动态配置XmlSerializer的属性重写来实现,不需要把列表包装到Test类里。下面是具体的实现思路和代码示例:
核心思路
XmlSerializer提供了带XmlAttributeOverrides参数的构造函数,允许我们在运行时覆盖默认的序列化规则——相当于给任意List<Bar>对象动态添加XmlArray和XmlArrayItem特性,和你在Test类成员上的配置效果完全一致。
完整代码示例
using System; using System.Collections.Generic; using System.IO; using System.Xml.Serialization; [XmlInclude(typeof(Foo1)), XmlInclude(typeof(Foo2))] public abstract class Bar { public string s; } public class Foo1 : Bar { } public class Foo2 : Bar { } class Program { static void Main() { // 准备测试数据 var barList = new List<Bar> { new Foo1 { s = "我是Foo1实例" }, new Foo2 { s = "我是Foo2实例" }, new Bar { s = "我是Bar基类实例" } }; // 构建属性重写配置 var overrides = new XmlAttributeOverrides(); var xmlAttributes = new XmlAttributes(); // 为每个派生/基类指定对应的XML元素名 xmlAttributes.XmlArrayItems.Add(new XmlArrayItemAttribute("derived1", typeof(Foo1))); xmlAttributes.XmlArrayItems.Add(new XmlArrayItemAttribute("derived2", typeof(Foo2))); xmlAttributes.XmlArrayItems.Add(new XmlArrayItemAttribute("base", typeof(Bar))); // 设置根元素名为"Bars"(和Test类里的XmlArray属性一致) overrides.Add(typeof(List<Bar>), new XmlRootAttribute("Bars")); // 将配置应用到List<Bar>类型 overrides.Add(typeof(List<Bar>), xmlAttributes); // 创建自定义XmlSerializer,必须传入XmlInclude的类型列表 var serializer = new XmlSerializer( typeof(List<Bar>), overrides, new[] { typeof(Foo1), typeof(Foo2) }, null, null ); // 执行序列化并输出结果 using (var writer = new StringWriter()) { serializer.Serialize(writer, barList); Console.WriteLine(writer.ToString()); } } }
关键细节说明
- XmlAttributeOverrides的作用:它允许我们在运行时为目标类型(这里是
List<Bar>)添加或修改序列化特性,完全替代了在类成员上标注XmlArrayItem的静态方式。 - 根元素配置:通过
XmlRootAttribute把默认的根元素名ArrayOfBar改成Bars,和Test类里的[XmlArray("Bars")]效果对齐。 - XmlInclude的必要性:构造
XmlSerializer时必须传入派生类类型,否则序列化过程中无法识别Foo1、Foo2,会抛出类型未被预期的异常。 - 性能提示:每次创建带
XmlAttributeOverrides的XmlSerializer都会生成动态程序集,建议对相同配置的序列化器进行缓存(比如用静态字典存储),避免频繁创建带来的性能损耗。
生成的XML效果
运行上述代码后,生成的XML会和方法A的输出完全一致:
<Bars> <derived1> <s>我是Foo1实例</s> </derived1> <derived2> <s>我是Foo2实例</s> </derived2> <base> <s>我是Bar基类实例</s> </base> </Bars>
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

