C#二进制序列化和AssemblyFormat与FormatterAssemblyStyle.Full

Ziv*_*vka 4 .net c# serialization visual-studio-2010 winforms

我很想知道如何使用FormatterAssemblyStyle.Full的二进制格式化程序的汇编格式来"中断"反序列化.

文件对这一规定:

在完整模式下,反序列化期间使用的程序集必须与序列化期间使用的程序集完全匹配.

我认为,如果我序列化一个对象(_person是一个带有值类型字段的简单类)与版本1.0.0.0的程序集,然后尝试用程序集的v1.2.0.0(更新AssemblyInfo.cs)反序列化,我会得到一个反序列化异常.但是,它成功地反序列化.

我错过了什么吗?

我正在使用以下序列化文件:

                BinaryFormatter formatter = new BinaryFormatter();
                formatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full;

                using (Stream stream = new FileStream(fileName,
                                                     FileMode.Create,
                                                     FileAccess.Write,
                                                     FileShare.None))
                {
                    formatter.Serialize(stream, _person);
                    stream.Close();
                }
Run Code Online (Sandbox Code Playgroud)

然后使用以下代码反序列化:

                BinaryFormatter formatter = new BinaryFormatter();
                formatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full;

                using (Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    _person = (Person)formatter.Deserialize(stream);
                   stream.Close();
                }
Run Code Online (Sandbox Code Playgroud)

我还注意到使用FormatterAssemblyStyle.Full和FormatterAssemblyStyle.Simple生成的序列化文件都包含完整的版本信息(例如Version 1.0.0.0 Culture = neutral,PublicKeyToken = null) - 我认为Simple不会添加所有这些信息?(请参阅从格式化和组装名节)

更新1:

到目前为止我唯一看到的区别是,如果我使用Simple,那么我不必OptionalField属性放在序列化类中的新字段中,以便成功地对旧版本进行反序列化.如果我使用Full,那么它会抛出异常,除非我将OptionalField属性放在新字段上.这是唯一的区别,如果使用不强大的程序集??

请参阅了解详情.

提前致谢

Pat*_*tko 9

文档FormatterAssemblyStyle.Full实际上说了两件事:

  1. Assembly.Load方法将用于加载程序集.
  2. 反序列化期间使用的程序集必须与序列化期间使用的程序集完全匹配.

通过Assembly.Load加载装配

加载程序集时,还会检查程序集版本,但仅当程序集具有强名称时才会检查.大会版本控制的文件说:

运行时为了版本控制而区分常规和强命名的程序集.仅对具有强名称的程序集进行版本检查.

要强烈命名程序集,请按照如何:使用强名称签署程序集中的步骤操作.此外,即使您为没有强名称的程序集指定了完全限定的程序集名称,AssemblyName文档也会声明以下内容:

提供显示名称时,约定StrongName = null或PublicKey = null表示需要绑定和匹配简单命名的程序集.

因此,即使使用Assembly.Load方法,运行时也将始终加载常规程序集而不进行版本检查.

完全反序列化

整个程序集必须与反序列化期间使用的程序集匹配并不完全正确.只有正反序列化的类(以及对象图中的所有其他类)才能匹配.在每个反序列化的类中,只有字段应该匹配,您可以随意添加新方法.版本容忍序列化更详细地介绍了这一点.

总而言之,是的,如果你没有强名称的程序集,那么唯一的区别在于反序列化的容忍程度.因此,您可以使用Full反序列化OptionalFieldAttributeSimple反序列化,具体取决于您的上下文.