序列化树视图时丢失数据

本文关键字:数据 视图 序列化 | 更新日期: 2023-09-27 18:13:02

我正在用c#写一个程序,它将数据分配给一个类,然后将该类分配给树视图节点的标签值。

我能够序列化我的树视图文件使用一个答案我发现在这里:保存一个树视图的内容到一个文件,然后加载它。

然而,使用此方法在反序列化文件时丢失了所有节点的Tag,或者更有可能的是,它们甚至没有被序列化。

是否有可能在使用这种方法序列化时保留节点的Tag值?如果有,怎么做?

序列化树视图时丢失数据

要被BinaryFormatter成功序列化,您的Tag对象必须标记为[Serializable],这表明可以通过序列化其公共和私有字段来成功序列化和反序列化。如果这样标记,那么它序列化为TreeNode的一部分,如参考源所示:

[TypeConverterAttribute(typeof(TreeNodeConverter)), Serializable,
DefaultProperty("Text"),    
SuppressMessage("Microsoft.Usage", "CA2240:ImplementISerializableCorrectly")]
public class TreeNode : MarshalByRefObject, ICloneable, ISerializable {
    object userData;
    protected virtual void Serialize(SerializationInfo si, StreamingContext context) {
        // SNIP storage of irrelevant fields.
        if (userData != null && userData.GetType().IsSerializable) {
            si.AddValue("UserData", userData, userData.GetType());
        }
    }
    public object Tag {
        get {
            return userData;
        }
        set {
            userData = value;
        }
    }
 }

注意,如果你的Tag对象不是可序列化的,它将被静默跳过;

我想改进一下这个答案。

在类之前使用[Serializable()]和从ISerializable派生的类是很重要的。

此外,可以接受反序列化参数的重载构造函数 GetObjectData函数的存在也很重要。

本质上,GetObjectData函数为序列化程序提供了以字符串形式访问所有信息的能力,而重载的NodeTag构造函数可以重新解释序列化的字符串数据并将其加载回对象。

我必须以以下方式构造我的类(这是半伪代码):
[Serializable()]
class NodeTag : ISerializable
    {
        public NodeTag(string Subnet)
        {
         Broadcast_Address = Stuff;
         Network_Name = Stuff;
         CIDR_Value = Stuff;
         }
        public string Network_Name { get; set; }
        public string CIDR_Value { get; set; }
        public string Broadcast_Address { get; set; }
        //Deserializer - loads back from file data
        //This is an overloaded function that defines the data object when it is being reconstituted
        public NodeTag(SerializationInfo info, StreamingContext context)
        {
            Network_Name = (String)info.GetValue("Network_Name", typeof(string));
            CIDR_Value = (String)info.GetValue("CIDR_Value", typeof(string));
            Broadcast_Address = (String)info.GetValue("Broadcast_Address", typeof(string));
        }
        //Serializer - loads into file data
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Network_Name", Network_Name);
            info.AddValue("CIDR_Value", CIDR_Value);
            info.AddValue("Broadcast_Address", Broadcast_Address);
        }
    }