12

Microsoft .Net バイナリ デシリアライゼーション エラーのソース タイプを公開するためにランタイム プラットフォームをインストルメント化する方法についての洞察を探しています。

使用しBinaryFormatter.Deserialize(StreamingContextStates.CrossMachine)ていて、型の 1 つが現在のバイナリに存在しない場合。エラーをスローする代わりに、.Net は object を挿入します[TypeLoadExceptionHolder]。特にコレクションの場合、これはすぐには問題になりません。

その後、コレクションがアプリケーション層間の伝送のためにシリアライズされるとき。[TypeLoadExceptionHolder]シリアル化できないため、プラットフォームは「シリアル化の失敗」を受け取ります。そのため、結果として生じるエラーは、問題の原因となったソース タイプに関する手がかりを実際に提供するのには役に立ちません。現在、何百万行ものプラットフォームに新しいタイプを追加した開発者 (何百人もいる) を見つけるための狩り (時間の浪費) が行われています。

この問題は、プラットフォームのセッション キャッシュをサポートするために使用されるシリアライゼーション ストリームが原因で、ある程度の頻度で発生します。コードはかなりの頻度で段階的に展開されます。顧客のページ要求は、展開期間中にコードベースの古いバージョンと新しいバージョンの間でバウンスする可能性があります。不注意に新しいタイプを導入すると、古いバージョンのページリクエストが爆発する原因になります。

ランタイム リッチ エラー/トラップの提供に関するご意見をお待ちしております。


(SerializationException) 
Type 'System.Runtime.Serialization.TypeLoadExceptionHolder' in Assembly 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable. 
- at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) 
- at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) 
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() 
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) 
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) 
- at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo) 
- at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) 
- at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) 
4

1 に答える 1

6

1 つの方法として、逆シリアル化中に型名SerializationBinderをオーバーライドしてチェックするカスタムを使用することができます。BindToType

達成したいことに応じて、不明なタイプを特定するときに次のいずれかを実行できます。

  • 例外を発生させる (悲観的): 早い段階で問題をキャッチし、カスタム メッセージまたは例外で型を簡単に識別できます。

  • 型名をログに記録する (楽観的): 不明な型が問題ないシナリオがある場合、後でシリアル化中に例外が発生した場合に、例外を診断するために必要な詳細がログに記録されます。

タイプ名の特性に応じて別のアプローチを選択することもできます (つまり、タイプがアプリケーションの一部またはサード パーティ ライブラリの一部のように見える場合)。

逆シリアル化中に作成されたインスタンスには、解決できなかった型の名前を含むTypeLoadExceptionHolder非パブリック メンバーが含まれています。TypeNameただし、インスタンスはSerializationException後で遭遇するものからは利用できません。それでも、信頼されたコンテキストでのリフレクションを介してのみ値を利用できます。

public class CustomSerializationBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        Type t = Type.GetType(string.Concat(typeName, ", ", assemblyName));

        if (t == null)
        {
            throw new SerializationException(string.Format("Type {0} from assembly {1} could not be bound.", typeName, assemblyName));
        }

        return t;
    }

    public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        base.BindToName(serializedType, out assemblyName, out typeName);
    }
}

...

BinaryFormatter.Binder = new CustomSerializationBinder();
于 2011-09-21T01:40:22.420 に答える