2010-07-14 4 views
12
.

. Я ищу информацию о том, как настроить платформу времени выполнения, чтобы выявить исходный тип сбоя двоичной десериализации Microsoft .Net..Net Двоичная десериализация. Обнаружение отказа/криминализация для платформы времени исполнения.

При использовании BinaryFormatter.Deserialize(StreamingContextStates.CrossMachine) и один из типов не существует в текущих двоичных файлах; вместо того, чтобы бросать ошибку, .Net вставляет объект [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

Ну, один подход можно принять, чтобы использовать пользовательские SerializationBinder, который отменяет BindToType и проверяет имя типа во время десериализации.

В зависимости от того, что вы хотели бы достичь, если определить неизвестный тип можно либо:

  • сгенерирует исключение (пессимистический): Поймай вопрос на ранней стадии и может легко идентичность типа с пользовательское сообщение или исключение.

  • Запишите имя типа (оптимистичный): если есть сценарии, в которых неизвестные типы в порядке, регистрация обеспечит детали, необходимые для диагностики исключений, если они возникнут позже во время сериализации.

Вы также можете выбрать другой подход в зависимости от характеристик имени типа (то есть, если тип, кажется, часть вашего приложения или части 3-сторонней библиотеки).

Экземпляр 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();