自定义可序列化泛型集合Xml序列化时Setting属性未被序列化的原因
问题:自定义泛型集合的Setting属性未被XmlSerializer序列化?
自定义泛型集合类
[Serializable] public class ArrayOfItems<T> : IEnumerable<T> { [XmlAttribute("Setting")] public bool Setting { get; set; } = false; [XmlAnyElement] public List<T> Items { get; set; } = new List<T>(); public IEnumerator<T> GetEnumerator() { return Items.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { IEnumerator iterator = ((IEnumerable<T>)this).GetEnumerator(); while (iterator.MoveNext()) { yield return iterator.Current; } } public void Add(T Object) { Items.Add(Object); } }
序列化代码
ArrayOfItems<int> ints = new(); ints.Items.Add(0); ints.Items.Add(1); using (StreamWriter writer = new StreamWriter(@"C:\test.xml", false, System.Text.Encoding.Unicode)) { XmlSerializer serializer = new(ints.GetType()); serializer.Serialize(writer, ints); writer.Flush(); writer.Close(); }
生成的XML内容
<?xml version="1.0" encoding="utf-16"?> <ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <int>0</int> <int>1</int> </ArrayOfInt>
原因分析
当类实现了IEnumerable(或IEnumerable<T>)接口时,XmlSerializer会默认将其识别为集合类型,此时序列化逻辑会优先处理集合元素,自动忽略类中的其他属性(哪怕标记了[XmlAttribute])。这是XmlSerializer针对集合类型的固有规则:只输出集合内的元素,而非类的完整属性集合。
解决方案
方案1:移除IEnumerable接口实现(推荐)
如果不需要让类直接作为集合被遍历,可以移除接口实现,通过[XmlArray]和[XmlArrayItem]控制集合元素的序列化,同时保留Setting属性:
[Serializable] [XmlRoot("ArrayOfItems")] public class ArrayOfItems<T> { [XmlAttribute("Setting")] public bool Setting { get; set; } = false; [XmlArray("Items")] [XmlArrayItem("Item")] public List<T> Items { get; set; } = new List<T>(); public void Add(T obj) { Items.Add(obj); } }
方案2:保留IEnumerable并调整属性标记
如果必须保留接口实现,可以将集合属性标记为[XmlElement],让XmlSerializer同时序列化属性和集合元素:
[Serializable] public class ArrayOfItems<T> : IEnumerable<T> { [XmlAttribute("Setting")] public bool Setting { get; set; } = false; [XmlElement(typeof(T))] public List<T> Items { get; set; } = new List<T>(); public IEnumerator<T> GetEnumerator() { return Items.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public void Add(T obj) { Items.Add(obj); } }
修改后生成的XML会包含Setting属性:
<?xml version="1.0" encoding="utf-16"?> <ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Setting="false"> <int>0</int> <int>1</int> </ArrayOfInt>
方案3:自定义序列化逻辑(复杂场景)
如果需要更精细的控制,可以实现IXmlSerializable接口,手动编写序列化和反序列化的逻辑,不过这种方式代码量较大,适合特殊需求场景。
内容的提问来源于stack exchange,提问作者ElDog
相关产品推荐
相关产品推荐

