派生自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
相关产品推荐
相关产品推荐

