Effective C# 原则25: 让你的类型支持序列化
2009-02-19 08:16:24 来源:WEB开发网序列化流是以键/值对应的方法来保存每一个元素的。默认的特性生成的代码是以变量名做为键来存储值。当你添加了ISerializable接口后,你必须匹配键名以及变量顺序。这个顺序就是在类中定义时的顺序。(顺便说一句,这实际上就是说重新排列类中的变量名或者重新给变量命名,都会破坏对已经创建了的文件的兼容性。)
同样,我已经要求过SerializationFormatter的安全许可。如果不实行恰当的保护,对于你的类来说,GetObjectData()可能存在安全漏洞。恶意代码可能会产生一个StreamingContext,从而可以用GetObjectData()方法从对象中取得值,或者不断修改版本而取得另一个SerializationInfo,或者重新组织修改的对象。这就许可了恶意的开发者来访问对象的内部状态,在流中修改它们,然而发送一个修改后的版本给你。对SerializationFormatter进行许可要求可以封闭这个安全漏洞。这样可以确保只有受信任的代码才能恰当的访问类的内部状态(参见原则47)。
但在使用ISerializable接口时有一个弊端,你可以看到,我很早就让MyType成为密封(sealed)的,这就强制让它只能成为叶子类(leaf class)。在基类实现ISerializable接口就隐式的让所有派生类也序列化。实现ISerializable就意味关所有派生类必须创建受保护构造函数以及反序列化。另外,为了支持非密封类,你必须在GetObjectData()方法创建hook,从而让派生类可以添加它们自己的数据到流中。编译器不会捕获任何这样的错误,当从流中读取派生类时,因缺少恰当的构造构造函数会在运行时抛出异常。缺少hook的GetObjectData()方法也意味着从派生类来的数据不会保存到文件中。当然也不会有错误抛出。所以我要推荐:在叶类中实现Serializable。
我没有说这,因为它不工作:为了派生类的序列化,你的基类必须支持序列化。修改MyType ,让它成为了一个可序列化的基类,你要把序列化构造函数修改为protected,然后创建一个虚方法,这样派生类就可以重载它并存储它们的数据。
- ››Effective C# 原则40:根据需求选择集合
- ››Effective C# 原则41:选择DataSet而不是自定义的...
- ››Effective C# 原则42:使用特性进行简单的反射
- ››Effective C# 原则43:请勿滥用反射
- ››Effective C# 原则44:创建应用程序特定的异常类
- ››Effective C# 第6章:杂项
- ››Effective C# 原则45:选择强异常来保护程序
- ››Effective C# 原则47:选择安全的代码
- ››Effective C# 原则48:了解更多的工具和资源
- ››Effective C# 原则49:为C#2.0做好准备
- ››Effective C# 原则50:了解ECMA标准
- ››Effective C# 原则系列文章目录
更多精彩
赞助商链接