Десериализовать объект в сборку, которая теперь подписана и версирована - PullRequest
9 голосов
/ 23 апреля 2009

Я использовал для сериализации дерева с помощью BinaryFormatter (c #). Сборка, которая сделала именно это и которая содержит все сериализуемые классы, теперь имеет строгое имя, подписана и также получила новый номер версии (однако реализация не изменилась).

Когда я пытаюсь десериализовать массив byte [], строка

(TreeViewData)binaryFormatter.Deserialize(memoryStream);

создает исключение ArgumentNullException. (Имя_параметра: тип)

Я думал, что номер версии - это проблема, поэтому я реализовал собственный Binder. Я перезаписал метод BindToType и убедился, что версия исправлена ​​и возвращен правильный тип.

Однако в тот момент, когда программа покидает метод BindToType, я все еще получаю исключение, упомянутое выше.

Как мне это исправить?

Ответы [ 3 ]

12 голосов
/ 10 ноября 2009

Вы можете использовать SerializationBinder для решения этой проблемы:

private class WeakToStrongNameUpgradeBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        try 
        {
            //Get the name of the assembly, ignoring versions and public keys.
            string shortAssemblyName = assemblyName.Split(',')[0];
            var assembly = Assembly.Load(shortAssemblyName);
            var type = assembly.GetType(typeName);
            return type;
        }
        catch (Exception)
        {
            //Revert to default binding behaviour.
            return null;
        }
    }
}

Тогда

var formatter = new BinaryFormatter();
formatter.Binder = new WeakToStrongNameUpgradeBinder();

Вуаля, ваши старые сериализованные объекты могут быть десериализованы с помощью этого средства форматирования. Если тип также изменился, вы можете использовать SerializationSurrogate для десериализации старых типов в ваши новые типы.

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

3 голосов
/ 23 апреля 2009

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

Фундаментальная проблема, однако, заключается в том, что BinaryFormatter просто очень, очень хрупок, когда речь идет о таких вещах, как сборки. Черт, он достаточно хрупкий, даже в сборке .

Звучит так, как будто TreeViewData основано на дереве, поэтому мне интересно, был бы xml лучшим вариантом (то есть более устойчивым к версии). Если речь идет об эффективности, существуют пользовательские двоичные форматы (например, protobuf-net ), которые предлагают высокопроизводительную, устойчивую к версии, переносимую двоичную сериализацию. Если ваши данные уже сериализованы ... Интересно, может быть, пришло время изменить трек? Попробуйте использовать старую сборку для десериализации данных и переключитесь на более надежную стратегию сериализации.

1 голос
/ 10 ноября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...