Каков наилучший способ десериализации дженериков, написанных с другой версией подписанной сборки? - PullRequest
4 голосов
/ 05 апреля 2010

В других случаях было предложено просто добавить SerializationBinder, который удаляет версию из типа сборки. Однако при использовании универсальных коллекций типа, обнаруженного в подписанной сборке, этот тип строго версионируется на основе своей сборки.

Вот что я нашел работы.

internal class WeaklyNamedAppDomainAssemblyBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        ResolveEventHandler handler = new ResolveEventHandler(CurrentDomain_AssemblyResolve);
        AppDomain.CurrentDomain.AssemblyResolve += handler;

        Type returnedType;
        try
        {
            AssemblyName asmName = new AssemblyName(assemblyName);
            var assembly = Assembly.Load(asmName);
            returnedType = assembly.GetType(typeName);
        }
        catch
        {
            returnedType = null;
        }
        finally
        {
            AppDomain.CurrentDomain.AssemblyResolve -= handler;
        }

        return returnedType;
    }

    Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        string truncatedAssemblyName = args.Name.Split(',')[0];
        Assembly assembly = Assembly.Load(truncatedAssemblyName);
        return assembly;
    }
}

Однако, изменение глобального процесса связывания кажется мне довольно опасным. Странные вещи могут произойти, если сериализация происходит в нескольких потоках. Возможно, лучшее решение - это выполнить некоторые регулярные выражения для typeName?

Редактировать: Метод на основе строк не работает. Дженерики, очевидно, нуждаются в полном строго названном типе. Довольно отвратительно, если вы спросите меня.

Ответы [ 3 ]

2 голосов
/ 05 апреля 2010

Событие AssemblyResolve вызывается только в случае сбоя обычной привязки. Таким образом, все, что можно решить с помощью обычных методов, будет. Только операции десериализации могут вызвать событие, и у вас есть совершенно правильная стратегия для их устранения.

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

0 голосов
/ 05 ноября 2011

Это должно ответить на ваш вопрос: SerializationBinder со списком

При использовании универсальных типов в SerializationBinder.BindToType необходимо использовать слабые имена типов вместо полностью определенных имен типов.

0 голосов
/ 05 апреля 2010

Вместо того, чтобы сериализовать всю коллекцию, не могли бы вы пройтись по ней и сериализовать каждый элемент отдельно? Тогда вы можете использовать подход SerilizationBinder.

...