在给定类更改的情况下,在序列化之间键入对象



>我正在字典中存储与类型相关的信息,例如

Dictionary<Type, int> TypeInformation;
TypeInformation[typeof(OneOfMyOwnClasses)] = 42;

然后我(二进制)序列化我的应用程序的状态,包括上面的字典。

如果我更改代码中的OneOfMyOwnClasses,类型对象会发生什么情况?在什么情况下,类型对象在反序列化后保持不变?即什么时候会

if (TypeInformation[typeof(OneOfMyOwnClasses)] == 42)
MessageBox.Show("Yahoo !!!");

即使在反序列化应用状态后也给出肯定的结果?

  • 方法主体的更改是否保证在不同运行之间提供相同类型的对象?
  • 私有方法或字段名称的更改是否会更改有关类型对象的任何内容?
  • 更改公共方法(或字段)名称?
  • 更改命名空间或程序集?
  • 类名本身的变化?(据说不是... ;-)
  • )

最后,考虑到所有这些,是否有任何充分的理由不序列化类型信息,是否有更好但更复杂的方法(例如创建 GUID 等)?

假设你的意思是BinaryFormatter,那么:

  1. 更改类型的类型、命名空间或程序集标识将破坏序列化程序(如果存储类型的实例或Type对象本身
  2. )
  3. 更改类型上字段的名称或类型将破坏序列化程序(如果要存储该类型的实例)

在这两种情况下,都有办法通过跳过复杂的箍来修复它,但通常不是一个好主意。根据我考虑的经验,BinaryFormatter根本不是一个好的选择,除非在非常特定的情况下(特别是两个正在运行的应用程序之间的 RPC,这些应用程序必须运行完全相同的代码 - 例如应用程序域隔离),并且如果您的目的是通用存储,您通常最好使用其他任何东西.我特别倾向于protobuf-net(它是"二进制"的,因为它实现了谷歌的二进制"协议缓冲区"格式),但我承认有偏见。JSON和XML在可移植性方面也是不错的选择,尽管它们几乎总是具有更大的输出和(稍微)较慢的处理速度。

请注意,大多数序列化程序在序列化Type对象时将使用完全限定的名称,因此上面的第 1 点将适用于大多数序列化程序,尽管可能存在每个序列化程序的更改方式。不过,坦率地说,我会说,如果你正在序列化一个Type实例,你做错了什么,最好作为对某些外部引用的手动键控查找(例如,可以通过类型的属性)。例如:

[SomeMarker("abc")]
class OneOfMyOwnClasses {...}

然后使用反射获取SomeMarkerAttribute实例(以某种缓存方式),以便实际存储:

Type type = ...
string key = GetMarkerFromType(type); // "abc"
Dictionary<string, int> TypeInformation;
TypeInformation[key] = 42;

最新更新