Проблема десериализации в .NET - PullRequest
2 голосов
/ 08 сентября 2011

Я создал двоичный сериализованный файл моего объекта, чтобы использовать его в качестве файла базы данных для многих других проектов. Он работает довольно хорошо с тем же проектом, но когда я пытаюсь десериализовать этот файл из других проектов, он не будет. Появляющаяся ошибка гласит: "xxxx.xxxx сборка не найдена". Итак, как я должен сериализовать объект, чтобы сделать его независимым от сборки ???

Вот мой код:

            // Binary formatter
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("BinarySerialization.bin",
                                     FileMode.Create,
                                     FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, words);
            stream.Close();

Какие поправки мне нужно сделать ??? Пожалуйста, предоставьте мне пример рабочего кода / образец.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 08 сентября 2011

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

В вашем сценарии мне кажется, что правильной вещью здесь будет использование сериализатора на основе контракт ; например:

  • xml (XmlSerializer, DataContractSerializer и т. Д.)
  • JSON (JavascriptSerializer, JSON.net и т. Д.)
  • бинарный (protobuf-net и т. Д.)

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

Вы упоминаете "XML здесь небезопасны, так как я не хочу, чтобы пользователи знали содержимое основного файла базы данных". - в этом случае «protobuf-net» имеет «преимущество» в том, что он не читается человеком, но учтите: ни один из них, ни BinaryFormatter не являются зашифрованными ; если бы я хотел, я мог бы получить содержимое, если бы я действительно, очень хотел. Если вам нужна надежная защита, используйте правильное шифрование. В этом случае ваш код становится (помимо нескольких атрибутов маркера):

using(var stream = new FileStream("BinarySerialization.bin", FileMode.Create,
                                 FileAccess.Write, FileShare.None))
{
    Serializer.Serialize(stream, words);
}

Изменить, чтобы показать (по комментариям), как сериализовать Dictionary<string, List<Word>>, где Word - это класс с двумя строковыми членами (большая часть кода здесь просто используется для показа полного примера):

using System;
using System.Collections.Generic;
using System.IO;
using ProtoBuf;
[ProtoContract]
public class Word {
    [ProtoMember(1)]
    public string Foo { get; set; }    
    [ProtoMember(2)]
    public string Bar { get; set; }
}
static class Program {
    public static void Main() {
        var data = new Dictionary<string, List<Word>>{
            {"abc", new List<Word> {
                new Word { Foo = "def", Bar = "ghi"},
                new Word { Foo = "jkl", Bar = "mno"}
            }},
            {"pqr", new List<Word> {
                new Word {Foo = "stu", Bar = "vwx"}
            }}
        };
        using(var file = File.Create("my.bin")) {
            Serializer.Serialize(file, data);
        }
        Dictionary<string, List<Word>> clone;
        using(var file = File.OpenRead("my.bin")) {
            clone = Serializer.Deserialize<
                 Dictionary<string, List<Word>>>(file);
        }
        foreach(var pair in clone) {
            Console.WriteLine(pair.Key);
            foreach(var word in pair.Value){
                Console.WriteLine("\t{0} | {1}", word.Foo, word.Bar);
            }
        }    
    }
}
1 голос
/ 08 сентября 2011

Механизм сериализации в .NET создает вспомогательные dll типа для сериализации и десериализации ваших данных во время выполнения.Сначала он выдаст файл кода, который компилируется, а затем загружается вспомогательная dll для выполнения сериализации и десериализации.

Если по какой-то причине что-то происходит, когда создается вспомогательный .dll - скажем, ошибка компиляции- тогда среда выполнения не найдет эту DLL.

Если имя dll в вашем случае является каким-то случайным символом, то я бы сказал, что вы столкнулись с проблемой, описанной выше.Вы можете устранить это, включив недокументированный переключатель.См. Следующую статью:

КАК: Отладка в сгенерированную сборку .NET XmlSerializer

1 голос
/ 08 сентября 2011

Я бы поместил все мои модели, которые должны быть сериализованы, в отдельную сборку.Затем вы ссылаетесь на эту сборку везде, где вам нужно десериализовать модели.

Если вам не нужен какой-то генератор, который воссоздает модели на основе некоторой схемы (так же, как WCF делает с ее утилитами) или использует простые форматы, напримерXML для сохранения ваших данных.

...