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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:20:35