8

問題

アセンブリのバージョン 1.0 でシリアル化された (プライベートMethodInfoフィールドを持つ) オブジェクトは、そのアセンブリのバージョン 1.1 では逆シリアル化されません (SerializationException必要なメソッドが見つからないため、 a がスローされます)。

変更点

.NET 4.5 では、MemberInfoビアのシリアル化メカニズムMemberInfoSerializationHolderが変更されていることがわかりました。過去 (.NET 4.0 まで) では、シリアル化されたデータはメソッド シグネチャ (単純な で取得MethodInfo.ToString()) でした。.NET ソース コードのコメントによると、次のSerializationToString()理由で取得した 2 番目の署名を追加しました。

m_signature は、あいまいな場合があるメンバーの ToString() 表現を格納します。同じメソッドまたはプロパティの複数のオーバーロードは、同一の ToString() にすることができます。m_signature2 は、メンバーごとに一意である必要がある SerializationToString() 表現を格納します。4.0 以降の CLR バージョンでのみ作成および使用されます。

私が見ることができるのは、MemberInfoSerializationHolder.GetRealObject()この(簡略化された)コードを使用してメソッドを解決することです(.NETソースコードから):

for (int i = 0; i < methods.Length; i++)
{ 
    if (m_signature2 != null) // SerializationToString() signature
    {
        if (((RuntimeMethodInfo)methods[i]).SerializationToString().Equals(m_signature2))
        { 
            methodInfo = methods[i];
            break; 
        } 
    }
    else 
    {
        if (methods[i].ToString().Equals(m_signature))
        { 
            methodInfo = methods[i];
            break; 
        }
    }
}

if (methodInfo == null)
    throw new SerializationException(...);

この場合、m_signature2アセンブリ名にバージョン情報が含まれているため署名が見つからないため、逆シリアル化は失敗し、String.Equals()一致MyAssembly, Version=1.0.0.0せずMyAssembly, Version=1.1.0.0、例外がスローされます。

質問

新しい検索が失敗した場合 (少なくとも既存のコードとの互換性のため) 、フレームワークは古い検索方法にフェールバックすることが予想されます。アセンブリのすべてのバージョンが実行時に解決された後 (そして新しいバージョンが既定で読み込まれる)、この比較が で行われる理由がわかりません。そこでアセンブリ バージョンを解決できないことに同意しますが、厳密な検索が失敗した場合、それを削除/無視することがあります。String.Equals()

シリアライズするのはひどいことだとわかっていMethodInfoますが、現時点では、この修正には (アーキテクチャとコードの両方で) あまりにも多くの変更が含まれる可能性があり、誰もその古いコードでこのリファクタリングを開始することはありません (さらに、アーカイブのバイナリ互換性は、古いものと新しいものの両方で維持する必要があります)バージョン、両方向)。

これまでのところ試していませんが、この問題はデリゲートにも当てはまりますか? この問題を回避するための解決策 (属性または小さなコード変更) はありますか?

4

2 に答える 2

2

私が考えることができる最良の方法は、実装することですISerializableMSDN

プロパティを持つオブジェクトにこのインターフェイスを実装すると、MethodInfoシリアライゼーション/デシリアライゼーションをほぼ完全に制御できます。

欠点は、他のすべてのプロパティも一般的な方法で処理する必要があることです。しかし、できるはずです。

于 2013-01-07T17:13:23.123 に答える
1

最後に、この問題を自分で完全に解決することはできませんでした。古い動作を模倣するためにのカスタム実装ISerializableを使用して実装しようとしました (4.0 バージョンのコードを貼り付けただけです)。新しいアーカイブでは問題なく動作しますが、このシナリオの古い (デプロイされた) アプリケーションでは動作しません。すでに出荷されているアプリケーションは機能しないため、この問題を解決する方法が見つかりませんでした (パッチが適用されても実行可能でない場合を除きます)。MemberInfoSerializationHolder

新しいビルドでは実装が少し変更されているのを見ましたが、同じ名前のメソッドが複数ある場合にのみ問題が事前設定されます (署名が使用されます)。

于 2013-03-23T21:53:44.420 に答える