2009-09-11 4 views
2

Мы сохраняем и читаем файлы посредством (де) сериализации класса с именем «DocumentClass». Все работало хорошо, пока мы не добавили еще 2 поля в класс документов. (Мы считаем, что это проблема)Проблема сериализации

Когда мы теперь пытаемся открыть файлы, которые были сериализованы предыдущей редакцией, мы получаем сообщение об ошибке.

System.ArgumentException: Объект типа 'System.Int32' не может быть преобразован в тип 'System.String'. на SoftwareProject.Componenten.Bestand.DocumentClass.d (String A_0) в de..ctor (String A_0) в g.a (Строка A_0)

Способ генерации ошибки является метод "Чтение". (DocumentClass.d() - это запутанное имя)

Но все становится страннее: когда мы открываем файл в режиме отладки VS, ошибка не генерируется, но все поля в классе документов равны 0 или null ???

Мы потеряли здесь ... Пожалуйста, помогите ... Мы добавили [OptionalField] атрибут новых полей, но это не помогает ..

Почему все значения нулевые в отладочных Режим ?? И откуда исходит ошибка времени выполнения? Как мы можем его отладить?

Спасибо заранее!

public static DocumentClass Read(string fullFilePath) 
{ 

    DocumentClass c = new DocumentClass(); 
    Stream s = File.OpenRead(fullFilePath); 
    BinaryFormatter b = new BinaryFormatter(); 
    //b.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple; 
    b.Binder = new MyCustomBinder(); 

    try 
    { 
     c = (DocumentClass)b.Deserialize(s); 
    } 
    catch(Exception exc) 
    { 
     s.Close(); 
     throw exc; 
    } 
    finally 
    { 
     s.Close(); 
    } 
    return c; 
     } 


     public class MyCustomBinder : SerializationBinder { 

    public override Type BindToType(string assemblyName, string typeName) { 
     Type tyType = null; 
     string sShortAssemblyName = assemblyName.Split(',')[0]; 
     Assembly[] ayAssemblies = AppDomain.CurrentDomain.GetAssemblies(); 
     if (sShortAssemblyName.ToLower() == "debugAssemblyName") 
     { 
     sShortAssemblyName = "AppAssemblyName"; 
     } 
     foreach (Assembly ayAssembly in ayAssemblies) { 
     if (sShortAssemblyName == ayAssembly.FullName.Split(',')[0]) { 
     tyType = ayAssembly.GetType(typeName); 
     break; 
     } 
     } 
     return tyType; 
    } 
} 

ответ

0

Предполагаете, вы используете BinaryFormatter? Этот сериализатор, как известно, хрупкий, поскольку он (по умолчанию) включает имя поля в потоке; это влияет на обфускацию particularly badly. Предположительно, обфускатор теперь выбирает новое имя для полей (возможно, случайно, возможно, из-за новых полей), и поэтому он не может десериализоваться правильно.

Несколько вариантов:

  • не запутать DTO
  • реализовать ISerializable поэтому имена полей не имеет значения
  • использовать сериалайзер, который не заботится о именах полей

Я лично выбрал последнее, но я немного предвзято; -p Я знаю людей, использующих protobuf-net с обфускационными классами; данные включают только числовые маркеры, поэтому значение действительно не отображается (за исключением, конечно, проверки данных - почтовых кодов и т. д., но это задача шифрования).

Смежные вопросы