从Dictionary继承的对象上的C#反序列化异常

标签 c# dictionary serialization deserialization

为什么我在类的第一个实现中出现反序列化异常“未找到反序列化类型为‘SerializeTest.TryMe’的对象的构造函数”,但在第二个实现中却没有?

第一次实现:

[Serializable]
public class TryMe : IDictionary<int, string>
{
    Dictionary<int, string> _dictionary = new Dictionary<int, string>();
    public TryMe() {}

    public IEnumerator<KeyValuePair<int, string>> GetEnumerator()
    {
        return _dictionary.GetEnumerator();
    }
    // all other IDictionary members are implemented below...
    ......
}

第二次实现:

[Serializable]
public class TryMe : Dictionary<int, string>
{
    public int Dummy { get; set; } = 5;
    public TryMe() {}
}

序列化/反序列化代码:

var tryMe = new TryMe();
tryMe[5] = "a"; tryMe[9] = "b"; tryMe[4] = "c";
using (var fs = new FileStream(@"D:\11.obj", FileMode.Create))
{
    var formatter = new BinaryFormatter();
    formatter.Serialize(fs, tryMe);
}

tryMe = null;
using (var fs = new FileStream(@"D:\11.obj", FileMode.Open))
{
    var formatter = new BinaryFormatter();
    tryMe = (TryMe)formatter.Deserialize(fs); // Exception here with 2nd implementation of TryMe!!
}

还有其他序列化问题,我应该在什么时候继承 IDictionary 以及什么时候继承 Dictionary
是否有规范的方式/规则?

最佳答案

问题:

Why am I getting deserialization exception "The constructor to deserialize an object of type 'SerializeTest.TryMe' was not found" in the first implementation of class but not in the second?

答案:

接口(interface)文档 ISerializable 说:

The ISerializable interface implies a constructor with the signature constructor (SerializationInfo information, StreamingContext context). At deserialization time, the current constructor is called only after the data in the SerializationInfo has been deserialized by the formatter.

(我们将 constructor (SerializationInfo information, StreamingContext context) 称为反序列化构造函数。)

所以从文档中我们知道对于实现 ISerializable 的类反序列化构造函数是必需的。

Dictionary<TKey, TValue> 工具 ISerializable和你的类(class)TryMe (来自第二个示例)继承 Dictionary<TKey, TValue> .在反序列化期间,反序列化器考虑 TryMe作为实现 ISerializable 的类并寻找反序列化构造函数。反序列化器找不到它并抛出异常。

接口(interface) IDictionary<TKey, TValue> 不执行ISerializable因此不需要反序列化构造函数。在这种情况下 TryMe可以在没有反序列化构造函数的情况下反序列化。不抛出异常。


问题:

Also other then serialization issue when should I prefer to inherit IDictionary and when Dictionary?

Is there a canonical way/rule for this?

答案:

对于序列化,可以继承 Dictionary<TKey, TValue>IDictionary<TKey, TValue> .但是如果你继承Dictionary<TKey, TValue>必须将反序列化构造函数添加到您的类中。

您应该什么时候继承 IDictionary<TKey, TValue>什么时候Dictionary<TKey, TValue> ? 这取决于您解决的问题。一般我们可以考虑两种情况:

  1. 如果您需要使用自定义实现一个类 IDictionary<TKey, TValue> Dictionary<TKey, TValue> 的功能和功能不满足您的要求,您更愿意继承IDictionary<TKey, TValue> .
  2. 如果 Dictionary<TKey, TValue> 的功能满足您的要求,并且您可以选择更改或添加您自己的功能,而不是您希望继承的功能 Dictionary<TKey, TValue> .

如果你实现 IDictionary<TKey, TValue>通过将适当的方法委托(delegate)给 Dictionary<TKey, TValue>就像在您的第一个示例中一样,您可能不需要实现 IDictionary<TKey, TValue> .在这种情况下,您应该继承 Dictionary<TKey, TValue> .

// Sample, when it is better to inherit Dictionary<TKey, TValue> 
// instead of implementing IDictionary<TKey, TValue>.
[Serializable]
public class TryMe : IDictionary<int, string>
{
    Dictionary<int, string> _dictionary = new Dictionary<int, string>();

    public IEnumerator<KeyValuePair<int, string>> GetEnumerator()
    {
        return _dictionary.GetEnumerator();
    }

    public string this[key]
    {
        get { return _dictionary[key]; }
    }

    // Other IDictionary<TKey, TValue> members are implemented the same way.
}

关于从Dictionary继承的对象上的C#反序列化异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60824181/

相关文章:

c# - SaveChanges 不适用于我的所有项目?

c# - 为什么我不能在公共(public)抽象类的方法中使用 Linq Where 子句?

c# - C#有解析多层级联JSON的库吗?

Python dict 是本地的,而不是引用

python - Python 中的数组索引

json - 没有使用 json 编码为 go 语言中的结构获取正确的数据

java - 在 Java 中序列化并保存 double [] 的 ArrayList

c# - 具有受控并行性和 AwaitAll 选项的异步任务

c# - 检查数据表中是否存在值?

c# - 如何在字典集合中使用 LINQ 将 TimeSpans 添加到一起