You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义可序列化泛型集合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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 12:23:19