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

派生自SerializableDictionary的类XML序列化丢失自定义属性,如何解决?

问题:SerializableDictionary派生类新增属性无法被XML序列化

我已成功使用XML序列化器对Microsoft.VisualStudio.Services.Common.SerializableDictionary<T1, T2>进行序列化。现在希望为其添加一个Guid字符串并一同序列化,因此创建了如下派生类:

public class SerializableDictWithGuid<T1, T2> : SerializableDictionary<T1, T2>, IMyInterface
{
    [XmlElement(ElementName = "idXml001")]
    public string Guid { get; set; } = string.Empty;
}

但使用以下XmlSerializeHelper代码序列化SerializableDictWithGuid时,XML输出中缺少该Guid字符串:

public class XmlSerializeHelper<T> where T : class
{
    public static string Serialize(T obj)
    {
        try
        {
            System.Xml.Serialization.XmlSerializer xsSubmit = new System.Xml.Serialization.XmlSerializer(typeof(T));

            using (var sww = new StringWriter())
            {
                using (XmlTextWriter writer = new XmlTextWriter(sww) { Formatting = Formatting.Indented })
                {
                    xsSubmit.Serialize(writer, obj);
                }

                return sww.ToString();
            }
        }
        catch (Exception ex)
        {
            logger.log(ex);
        }

        return string.Empty;
    }
}

最小复现代码示例:

SerializableDictWithGuid<string, string> test = new SerializableDictWithGuid<string, string>() { Guid = "123" };
XmlSerializeHelper<SerializableDictWithGuid<string, string>>.Serialize(test);

原因分析

SerializableDictionary<TKey, TValue>实现了IXmlSerializable接口来自定义XML序列化逻辑,当派生类继承这类自定义序列化的基类时,XmlSerializer会优先使用基类的WriteXml和ReadXml方法,不会自动处理派生类中新增的属性,导致Guid字段被忽略。


解决方法

方案一:重写IXmlSerializable方法,自定义序列化逻辑

在派生类中重写IXmlSerializable的相关方法,手动处理Guid属性的读写,同时保留基类对字典内容的序列化逻辑:

public class SerializableDictWithGuid<T1, T2> : SerializableDictionary<T1, T2>, IMyInterface
{
    [XmlElement(ElementName = "idXml001")]
    public string Guid { get; set; } = string.Empty;

    public new XmlSchema GetSchema()
    {
        return null;
    }

    public new void ReadXml(XmlReader reader)
    {
        // 先读取Guid元素
        reader.ReadStartElement();
        if (reader.Name == "idXml001")
        {
            Guid = reader.ReadElementString();
        }
        // 调用基类方法读取字典内容
        base.ReadXml(reader);
        reader.ReadEndElement();
    }

    public new void WriteXml(XmlWriter writer)
    {
        // 先写入Guid元素
        writer.WriteElementString("idXml001", Guid);
        // 调用基类方法写入字典内容
        base.WriteXml(writer);
    }
}

方案二:使用组合而非继承

创建一个包含SerializableDictionary和Guid属性的容器类,让XmlSerializer自动处理所有成员的序列化,避免自定义IXmlSerializable的复杂度:

public class DictWithGuid<T1, T2> : IMyInterface
{
    [XmlElement(ElementName = "idXml001")]
    public string Guid { get; set; } = string.Empty;

    [XmlArray("DictionaryItems")]
    [XmlArrayItem("KeyValuePair")]
    public SerializableDictionary<T1, T2> Dictionary { get; set; } = new SerializableDictionary<T1, T2>();
}

使用时直接实例化这个容器类:

DictWithGuid<string, string> test = new DictWithGuid<string, string>() 
{ 
    Guid = "123",
    Dictionary = { { "key1", "value1" }, { "key2", "value2" } }
};
XmlSerializeHelper<DictWithGuid<string, string>>.Serialize(test);

方案对比

  • 方案一保持了与原SerializableDictionary的继承关系,适合需要直接替换原有类型的场景,但需要手动维护序列化逻辑。
  • 方案二更简洁,无需处理IXmlSerializable的细节,适合不需要继承关系的场景,XML结构会更清晰。

内容的提问来源于stack exchange,提问作者chriscode

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 16:37:33