2009-10-28 5 views
5

Допустим, у меня есть классA, который содержит класс B, и оба являются [Serializable].Как изменить порядок десериализации с использованием BinaryFormatter в C#?

Я предположил, что в классе десериализации B сначала будет десериализован.

Это, однако, не так, как я мог подтвердить, просто зарегистрировавшись при каждом методе [OnDeserialized].

Теперь у меня есть следующий вопрос:

После десериализации CLASSA является полным, то предполагается установить себя вверх, используя значения из ClassB. К сожалению, классB еще не был десериализован в данный момент, поэтому classA настроен неправильно.

Моя проблема будет решена, если я могу заставить BinaryFormatter десериализовать класс B перед классом A или разрешить диаграмму объектов снизу вверх, а не сверху вниз.

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

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

+0

Какая платформа вы используете? – Lazarus

+0

В соответствии с названием вопроса, C# -> retagged – pyrocumulus

ответ

3

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

public class ClassA : ISerializable 
{ 
    private ClassB _dependency; 

    public ClassA(SerializationInfo information, StreamingContext context) 
    { 
     _dependency 
      = (ClassB)information.GetValue("_dependency", typeof(ClassB)); 

     // TODO: Get other values from the serialization info. 
     // TODO: Set up stuff from dependent object. 
    } 

    public SerializationInfo GetObjectData() 
    { 
     information.AddValue("_dependency", _dependency, typeof(ClassB)); 

     // TODO: Add other fields to the serialization info. 
    } 
} 
+0

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

+0

@Thorsten Lorenz: Вы нашли какое-либо другое решение? –

1

Я бы предположил, что просто использовал метод, обозначенный [OnDeserialized], для обработки любой инициализации после сериализации, требуемой вам, и не касайтесь порядка, в котором они десериализованы.

+0

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

+0

Очевидно, должно быть. Можете ли вы точно объяснить, что должно произойти между A и B, которые не могут быть обработаны событием после сериализации? –

+0

Детали не имеют значения, я думаю, что я объяснил это достаточно ясно: «После десериализации класса АА, он должен настроиться, используя значения из класса». Эти значения устанавливаются только после полного десериализации класса B. –

0

Эти два шага могли бы сделать трюк:

  1. Сделайте метод [OnDeserialized] класса B безопасным для вызова несколько раз.
  2. Метод [OnDeserialized] класса A явно вызывает метод [OnDeserialized] для объекта класса B.

The BinaryFormatter будет в конечном итоге вызова [OnDeserialized] метода объекта ClassB снова, но шаг 1 делает это безопасным.

1

Вы можете заставить classA реализовать интерфейс IDeserializationCallback. Его метод OnDeserialization будет вызываться только после завершения десериализации объекта всего объекта, включая объект класса B.