Сериализация графа с двунаправленными ссылками, (dll) импортированными типами и версиями ..? - PullRequest
1 голос
/ 28 декабря 2010

Хорошо, я уже задал несколько вопросов на SO по поводу сериализации, но я все еще застрял - поэтому я решил, что просто выложу весь свой случай вместо подзадач в надежде, что кто-то может засунуть мне нос правильное направление:)

Мое приложение похоже на «Quartz Composer» от Apple, что означает, что у меня есть древовидная структура связанных узлов.

Узлы определяются интерфейсом INode; фактические типы / классы узлов импортируются из DLL с использованием MEF, поэтому типы узлов не будут известны во время компиляции.

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

Я бы хотел сохранить свою «композицию» - все дерево узлов - в файле, желательно удобочитаемом, например, XML. Я действительно хочу избежать сохранения в собственном формате!

Так что мне нужно сериализовать:

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

  • Кроме того, я хотел бы сохранить информацию о версии для используемых классов узлов, чтобы можно было определить, была ли сохранена «композиция» с использованием более старой версии некоторого класса узла, чем используемый dll / узел класс в текущем приложении.

Ранее я указывал на DataContractSerializer, который выглядит как отличный инструмент для хранения моего дерева и полной поддержки двунаправленных ссылок.

Но если я хочу сериализовать свое дерево (интерфейс IComposition), он начинает жаловаться на неизвестные типы - мне нужно указать каждый конкретный тип, с которым он может столкнуться при сериализации дерева ...

А также у меня нет возможности указать, какая версия сборки использовалась для определенного класса узла.

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

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

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

1 Ответ

0 голосов
/ 28 декабря 2010

Вы можете сделать это с помощью BinaryFormatter или SoapFormatter . Эти средства форматирования работают с произвольными графами объектов и будут обрабатывать любых объектов, с которыми они сталкиваются (при условии, что типы объектов помечены [Serializable]), и будут правильно сохранять циклические ссылки. Если вам интересно посмотреть, как сериализуются объекты, используйте SoapFormatter, который будет выводить XML.

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

Чтобы справиться с управлением версиями, вы можете сделать что-то вроде этого:

[Serializable]
public class SomeVersionedClass : IDeserializationCallback
{
    private const int CURRENT_VERSION = 10;

    private int version = CURRENT_VERSION;

    void IDeserializationCallback.OnDeserialization(object sender)
    {
        if (version != CURRENT_VERSION)
            throw new ApplicationException(
                "Mismatch between serialized data version " + version +
                " and required version " + CURRENT_VERSION + ".");
    }
}

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

...