C#中继承List的派生类序列化时自定义字段未被序列化的问题求助
C# Xml序列化问题:继承List的自定义类字段未被序列化
序列化RegisterList对象时,仅List内的SingleRegister实例被保存,自定义的Reference和Description字段未被序列化。目前临时方案是通过组合(新增List<SingleRegister>成员变量)替代继承,以下是问题代码和正确解决思路:
问题代码
class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); RegisterList rl = new RegisterList(); rl.Reference = "This is my ref"; rl.Description = "This is the description of register list"; rl.Add(new SingleRegister("name1", "data1")); rl.Add(new SingleRegister("name2", "data2")); LoadAndStore<RegisterList>.Save(rl, "dummy.txt"); } } [Serializable] public class RegisterList: List<SingleRegister> { public string Reference; public string Description; } [Serializable] public class SingleRegister { public string Name; public string Data; public SingleRegister(string name, string data) { Name = name; Data = data; } public SingleRegister() { } } public static class LoadAndStore<T> { public static void Save(T obj, string filename) { XmlSerializer bf = new XmlSerializer(typeof(T)); // Create a file with the specified filename FileStream fs = new FileStream(filename, FileMode.Create); // Serialize the provided object and output to filestream bf.Serialize(fs, obj); // Flush the filestream buffer and close fs.Flush(); fs.Close(); } public static T Restore(string filename) { // Create a default for value types or null for reference types T e = default(T); // if specified file doesn't exist, return if (!File.Exists(filename)) return e; XmlSerializer bf = new XmlSerializer(typeof(T)); // Open file FileStream fs = new FileStream(filename, FileMode.Open); // Deserialize file contents and cast to specified type e = (T)bf.Deserialize(fs); // Close the filestream fs.Close(); return e; } }
问题原因
XmlSerializer对继承自ICollection(包括List<T>)的类型,默认仅序列化集合内的元素,会忽略类中额外定义的字段或属性——它将这类对象视为纯集合容器,而非带有附加数据的复杂对象。
解决办法
1. 优先推荐:使用组合替代继承(你的临时方案的规范实现)
面向对象设计中优先使用组合而非继承,同时能完美避免序列化问题。修改RegisterList类:
[Serializable] public class RegisterList { public string Reference; public string Description; // 用成员变量持有集合 public List<SingleRegister> Registers { get; set; } = new List<SingleRegister>(); }
调用时修改为:
rl.Registers.Add(new SingleRegister("name1", "data1")); rl.Registers.Add(new SingleRegister("name2", "data2"));
这样所有字段都会被XmlSerializer正常序列化和反序列化。
2. 若必须继承List:手动实现IXmlSerializable接口
通过实现IXmlSerializable接口,手动控制序列化和反序列化的过程,确保自定义字段和集合元素都被处理:
[Serializable] public class RegisterList : List<SingleRegister>, IXmlSerializable { public string Reference; public string Description; public XmlSchema GetSchema() => null; public void ReadXml(XmlReader reader) { // 读取自定义字段(此处以属性形式读取,也可改为子元素) Reference = reader.GetAttribute("Reference"); Description = reader.GetAttribute("Description"); // 读取集合元素 reader.ReadStartElement(); while (reader.NodeType != XmlNodeType.EndElement) { var serializer = new XmlSerializer(typeof(SingleRegister)); var item = (SingleRegister)serializer.Deserialize(reader); Add(item); } reader.ReadEndElement(); } public void WriteXml(XmlWriter writer) { // 写入自定义字段为XML属性 writer.WriteAttributeString("Reference", Reference); writer.WriteAttributeString("Description", Description); // 写入每个集合元素 foreach (var item in this) { var serializer = new XmlSerializer(typeof(SingleRegister)); serializer.Serialize(writer, item); } } }
这种方式需要手动处理XML的读写逻辑,适合必须保留继承关系的场景。
内容的提问来源于stack exchange,提问作者Ludovic Martin
相关产品推荐
相关产品推荐

