Проблема сериализации - PullRequest
2 голосов
/ 20 марта 2010

Я создал приложение для телефонной книги, и через некоторое время оно отлично работает. Мне понравилось делать обновление для моего приложения, и я начал с нуля. Я не унаследовал его от своего старого класса, и я тоже успешно справился «Я хочу перенести свои контакты из старого приложения в новый" по этой причине я создал класс адаптера в своем новом приложении со следующим кодом

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace PhoneBook
{
    class Adapter
    {
        PhoneRecord PhRecord;   //the new application object
        CTeleRecord TelRecord; //the old application object
        string fileName;

    public Adapter(string filename)
    {
        fileName = filename;
    }

    public void convert()
    {

        PhRecord = new PhoneRecord(); 
        TelRecord = new CTeleRecord();

        FileStream OpFileSt = new FileStream(fileName, FileMode.Open,FileAccess.Read);


        BinaryFormatter readBin = new BinaryFormatter();



        for (; ; )
        {
            try
            {
                TelRecord.ResetTheObject();

                TelRecord = (CTeleRecord)readBin.Deserialize(OpFileSt);

                PhRecord.SetName = TelRecord.GetName;
                PhRecord.SetHomeNumber = TelRecord.GetHomeNumber;
                PhRecord.SetMobileNumber = TelRecord.GetMobileNumber;
                PhRecord.SetWorkNumber = TelRecord.GetWorkNumber;
                PhRecord.SetSpecialNumber = TelRecord.GetSpecialNumber;
                PhRecord.SetEmail = TelRecord.GetEmail;
                PhRecord.SetNotes = TelRecord.GetNotes;
                PhBookContainer.phBookItems.Add(PhRecord);


            }
            catch (IOException xxx)
            {
                MessageBox.Show(xxx.Message);


            }
            catch (ArgumentException tt)
            {
                MessageBox.Show(tt.Message);
            }
            //if end of file is reached
            catch (SerializationException x)
            {
                MessageBox.Show(x.Message + x.Source);
                break;
            }

        }
        OpFileSt.Close();

        PhBookContainer.Save(@"d:\MyPhBook.pbf");

         }

    }
}

проблема в том, что при попытке прочитать файл, обработанный моим старым приложением, я получаю исключение сериализации с этим сообщением Телефонная книга "Отменить поиск сборки", версия = 1.0.0.0, культура = нейтральная, PublicK eyToken = ноль "

и источником исключения является mscorlib.

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

Ответы [ 3 ]

2 голосов
/ 20 марта 2010

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

Проблема в том, что, хотя эти два класса могут показаться идентичными, это не так, поскольку они находятся в разных сборках.

Рекомендуемый способ сделать это - всегда помещать сериализуемые классы в библиотеку классов. Тогда в вашей ситуации V2.0 вашего приложения может ссылаться на сборку V1.0, а затем вы можете десериализовать объекты.

Если ваши классы V1.0 отсутствуют в библиотеке классов (например, они встроены в исполняемый файл), вы можете создать классы V2.0 в библиотеке классов и добавить функциональность в свое приложение V1.0 для преобразовать классы в классы V2.0.

Публикуйте любые вопросы, которые у вас могут быть в комментариях.

Надеюсь, это поможет.

1 голос
/ 20 марта 2010

BinaryFormatter не очень терпим к изменениям сборки. Я давно пришел к выводу, что это нормально (почти) для транспорта, но не подходит для любого вида хранения - оно слишком хрупкое .

Короче говоря, я бы использовал другой сериализатор - но на основе контракта, а не на основе типа (поэтому любой тип с таким же cnotract может делиться данными):

  • во многих случаях XmlSerializer подойдет; у него есть некоторые ограничения (публичные типы и члены), но он работает обычно
  • с .NET 3.0, DataContractSerializer полезно
  • или, если вы хотите что-то вне кода библиотеки, protobuf-net очень быстрый и эффективный

Из них только DataContractSerializer будет в настоящее время поддерживать режим "графика" (а не деревья).

Если у вас есть существующие данные, с которыми вы боретесь, мне бы очень хотелось использовать старый код (или что-то очень близкое к нему) для перезаписи данных в форме контракта. Хотя вы говорите, что только что создали его, возможно, это не проблема.

0 голосов
/ 20 марта 2010

Как указывалось ранее, файл содержит полное имя сборки вашего класса, которое изменилось в вашем новом проекте. Если ваша сборка, имя класса и пространства имен совпадают, вы можете установить простой формат сборки на форматере:

BinaryFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;

Используется LoadWithPartialName, когда средство форматирования пытается загрузить этот тип. См. MSDN для получения дополнительной информации.

Вы также можете написать связыватель сериализации , чтобы устранить различия.

...