为什么调用构造函数而不是给我一个错误
本文关键字:错误 一个 构造函数 调用 为什么 | 更新日期: 2023-09-27 18:06:30
我正在为一款教育类游戏构建一个将类序列化为字符串并通过网络发送的系统。这招很管用。但是突然我注意到我自己看着我的代码,想知道"这是怎么工作的?"。
我所谈论的类被粘贴在下面,没有所有不必要的部分。
[Serializable]
public class Question : ISerializable
{
public readonly int id;
// Some more
// variables
// Default Constructor
public Question (int id /*, some more parameters*/)
{
this.id = id;
// Some initialization code
}
// Pay attention to this Constructor
public Question (SerializationInfo info, StreamingContext context)
{
id = (int)info.GetValue ("id", typeof (int));
// Some deserialization code
}
// Serialization overload method
public void GetObjectData (SerializationInfo info, StreamingContext context)
{
info.AddValue ("id", id, typeof (int));
// Some serialization code
}
// Serialization method actually used
static public string SerializeToString (Question p)
{
BinaryFormatter bf = new BinaryFormatter ();
using (MemoryStream ms = new MemoryStream ())
{
bf.Serialize (ms, p);
return Convert.ToBase64String (ms.ToArray ());
}
}
// This is where I'm going crazy
static public Question DeserializeFromString (string serialized)
{
BinaryFormatter bf = new BinaryFormatter ();
using (MemoryStream ms = new MemoryStream (Convert.FromBase64String (serialized)))
{
return (Question)bf.Deserialize (ms);
}
}
}
如果我在服务器端这样做:
// ...
string serialized = Question.SerializeToString (actualQuestion);
// Send "serialized" through the network
// ...
客户端:
// ...
// Receive a string
Question receivedQuestion = Question.DeserializeFromString (receivedString);
// ...
它工作!但是为什么呢?
我想知道的是在DeserializeFromString的返回语句中究竟发生了什么。
return (Question)bf.Deserialize (ms);
以下是我真正理解的:男朋友。反序列化(ms)接收一个用序列化字符串填充的内存流,并返回一个反序列化数据的Object。
- 变量如何存储在对象中,因为它不知道它的原型?(它不知道哪个类被序列化了)
- 为什么(问题)someObjectOfTypeObject调用特殊构造函数,而不是搜索显式转换的过载,或者,接收对象的构造函数(并且在这些搜索中失败,因为我没有实现它们)?
我想了解在低级别(或至少在编译器和运行时级别)发生了什么,如果可能的话,解释内存中发生了什么。
它不知道哪个类被序列化了
如果知道,BinaryFormatter包含流中序列化对象的类型信息。它记录程序集显示名称、程序集版本、程序集的公钥令牌、名称空间名称和类型名称。对于类中的每个字段,它记录字段名称和字段类型,与对象类型相同。
请注意,这会使二进制序列化变得有点危险,反序列化数据的代码需要能够找到完全相同的汇编。几年之后就很难了。
通过序列化到FileStream获得更深入的了解,使用十六进制查看器查看数据。您将很容易看到额外的元数据返回。
为什么(问题)someObjectOfTypeObject调用特殊构造函数
因为你继承了isserializable。BinaryFormatter检查你是否实现了该接口,然后自动寻找接受SerializationInfo和StreamingContext参数的构造函数。
更有趣的情况是,不实现isserializable。BinaryFormatter然后进行一个您自己无法完成的特技,它创建一个对象,而不需要调用构造函数。它使用一个进入CLR的后门来做到这一点。设置字段值,然后按照最初序列化时存储在内存中的方式重建对象。