4

FormatterAssemblyStyle.Full を使用したバイナリ フォーマッタのアセンブリ形式を使用して、逆シリアル化を "中断" する方法を知りたいです。

ドキュメントには、これについて次のように記載されています。

完全モードでは、逆シリアル化中に使用されるアセンブリは、シリアル化中に使用されるアセンブリと正確に一致する必要があります。

アセンブリのバージョン 1.0.0.0 でオブジェクト (値型フィールドを持つ単純なクラスである _person) をシリアル化すると、アセンブリの 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();
                }

次に、次を使用して逆シリアル化します。

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

また、FormatterAssemblyStyle.Full と FormatterAssemblyStyle.Simple を使用して生成されたシリアル化されたファイルには、両方とも完全なバージョン情報が含まれていることに気付きました (たとえば、バージョン 1.0.0.0 Culture = ニュートラル、PublicKeyToken = null) - Simple はこの情報をすべて追加しないと思いましたか? (こののフォーマッターとアセンブリ名のセクションを参照してください)

更新 1:

これまでに見た唯一の違いは、Simple を使用する場合、古いバージョンを正常に逆シリアル化するために、シリアル化されたクラスの新しいフィールドに属性を配置する必要がないことです。OptionalFieldFull を使用すると、OptionalField属性を新しいフィールドに配置しない限り、例外がスローされます。厳密な名前が付いていないアセンブリを使用する場合、これが唯一の違いですか??

詳しくはこちらをご覧ください。

前もって感謝します

4

1 に答える 1

9

のドキュメントには、FormatterAssemblyStyle.Full実際には次の 2 つのことが書かれています。

  1. Assembly.Loadメソッドを使用してアセンブリを読み込みます。
  2. 逆シリアル化中に使用されるアセンブリは、シリアル化中に使用されるアセンブリと正確に一致する必要があります。

Assembly.Load によるアセンブリの読み込み

アセンブリが読み込まれると、アセンブリのバージョンもチェックされますが、アセンブリに厳密な名前が付けられている場合のみです。アセンブリのバージョン管理に関するドキュメントは、次のように述べています。

ランタイムは、バージョン管理のために、通常のアセンブリと厳密な名前のアセンブリを区別します。バージョン チェックは、厳密な名前のアセンブリでのみ行われます。

アセンブリに厳密な名前を付けるには、 「方法:厳密な名前でアセンブリに署名する」の手順に従ってください。また、厳密な名前のないアセンブリの完全修飾アセンブリ名を指定した場合でも、AssemblyName ドキュメントには次のように記載されています。

表示名を指定する場合、規約 StrongName =null または PublicKey= null は、単純な名前のアセンブリに対するバインドと照合が必要であることを示します。

したがって、Assembly.Loadメソッドを使用している場合でも、ランタイムは常にバージョン チェックなしで通常のアセンブリを読み込みます。

完全逆シリアル化

アセンブリ全体が逆シリアル化中に使用されるアセンブリと一致しなければならないということは正確には当てはまりません。逆シリアル化されるクラス (およびオブジェクト グラフ内の他のすべてのクラス) のみが一致する必要があります。逆シリアル化された各クラスでは、フィールドのみが一致する必要があり、新しいメソッドを自由に追加できます。これについては、バージョン トレラント シリアライゼーションで詳しく説明しています。

要約すると、はい、厳密に名前が付けられたアセンブリがない場合、唯一の違いは、逆シリアル化の許容度です。したがって、コンテキストに応じて、逆シリアルFullOptionalFieldAttributeまたは逆シリアル化を使用します。Simple

于 2012-10-01T13:01:46.720 に答える