C # Binary Serialization and AssemblyFormat with FormatterAssemblyStyle.Full

I am curious to know how to โ€œsplitโ€ deserialization using the binary formatting assembly format using FormatterAssemblyStyle.Full.

the documentation points to this:

In full mode, the assembly used during deserialization must exactly match the assembly used during serialization.

I thought that if I serialize an object (_person, which is a simple class with value type fields) with assembly version 1.0.0.0, try to deserialize using assembly v1.2.0.0 (update AssemblyInfo.cs), I would get a deserialization exception . However, it is successfully deserialized.

Did I miss something?

I serialize to a file using the following:

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(); } 

and then deserialization using the following:

  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(); } 

I also noticed that the serialized file created using FormatterAssemblyStyle.Full and FormatterAssemblyStyle.Simple contains full version information (e.g. Version 1.0.0.0 Culture = neutral, PublicKeyToken = null). I thought Simple won't add all this information? (see section formatters and names names from this )

Update 1:

The only difference I've seen so far is that if I use Simple, then I donโ€™t need to place the OptionalField attribute for the new fields in the serialized class so that it successfully deacilates the old versions. If I use Full, it throws an exception unless I put the OptionalField attribute in new fields. Is this the only difference if you use assemblies that are not strong with the name

See more details.

Thank you in advance

+4
source share
1 answer

The documentation for FormatterAssemblyStyle.Full actually says two things:

  • The Assembly.Load method will be used to load the assembly.
  • The assembly used during deserialization must exactly match the assembly used during serialization.

Loading an assembly via Assembly.Load

When the assembly is loaded, the version of the assembly is also checked, but only if the assembly is heavily registered. The build version docs say the following:

Runtime distinguishes regular and strong names for version control purposes. Version checking occurs only with nodes with strong names.

To clearly name the assembly, follow the steps in How to Build with a Strong Name . In addition, even if you specify the fully qualified name of the assembly for the assembly without a strong name, AssemblyName docs report the following:

When a display name is supplied, the StrongName = null or PublicKey = null convention indicates that binding and matching with a simply named assembly is required.

Thus, even when using the Assembly.Load method, the runtime will always load regular assemblies without checking the version.

Full deserialization

It is not entirely true that the entire assembly must match the assembly used during deserialization. Only the class (and all other classes in the object graph) that is deserialized must match. In each deserialized class, only fields should match, you can add new methods as you wish. The Tolerant Serialization version describes this in more detail.

To summarize, yes, if you do not have strongly named assemblies, then the only difference is how tolerant deserialization is. This way you use Full deserialization with OptionalFieldAttribute or Simple deserialization, depending on your context.

+9
source

Source: https://habr.com/ru/post/1433757/


All Articles