2010-04-15 2 views
0

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

Для обработки версий старого объекта я написал конвертер, который десериализует объект в мыле и повторно сериализует его в двоичном формате.

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

Вот проблема: пространство имен, по-видимому, сериализовано с классом, поэтому я получаю сообщение об ошибке: не может использовать NamespaceA.class как NamespaceB.class. (Arrgh!)

Классы точно такие же; единственная проблема - пространство имен. Как я могу заставить инфраструктуру игнорировать пространства имен?

+3

Это похоже на то, что «две машины одинаковы, кроме одного красного, другого синего, а один из них - брод, а другой - volvo»? –

+0

Это больше похоже на то, что один из красных Volvos был продан дилером A, а другой красный Volvo был продан дилером B, поэтому они «разные». – user20493

+0

Не совсем, @alankdkd. Пространство имен является частью имени класса, @Lesse является правильным. –

ответ

2

Согласно этой публикации, Changing a namespace causes errors when using "BinaryFormatter.Deserialize" to reload object data saved while defined under a different namesapce(sic), вы должны посмотреть на класс SerializationBinder.

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

Вы посмотрели protocol buffers, в качестве примера?


Edit: Хорошо, прочитав ваш комментарий, и перечитывая свой вопрос, оказывается, ваш вопрос не имеет ничего общего с сериализации в конце концов, двоичный или иным образом.

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

Это, конечно, не работает прямо из коробки, и может быть легко воспроизведена без введения сериализации на всех, вы просто сделать это:

public class A { ... } <-- a class with some properties and stuff 
public class B { ... } <-- another class, with the same properties and stuff 

public void Test() 
{ 
    A a = new A(); 
    B b = a;   <-- you get the same problem as in your code here 
} 

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

Вы можете реализовать метод типа «клонирование», который принимает объект типа A, создает новый объект типа B и копирует все свойства и прочее.

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

У меня есть контрольный вопрос, который может дать нам некоторое представление о том, почему вы пытаетесь сделайте это: почему вы не можете десериализовать его как оригинальный тип и оставить его на этом? Почему вы должны его бросить?

+0

Проблема заключается в назначении десериализованного объекта (пространства имен) переменной класса имени в NamespaceB. Кажется, что десериализация успешна, поэтому новое связующее не поможет здесь. Спасибо, в любом случае. – user20493

+0

Deserializing в переменную типа Object works. Проблема заключается в том, чтобы превратить его в переменную правильного класса, чтобы я мог повторно сериализовать его, используя двоичный форматтер. Кажется, что я столкнулся бы с этой же проблемой с буферами протоколов. – user20493

+0

Лассе, я закончил делать что-то подобное; отдельное приложение, использующее одно и то же пространство имен, поэтому конфликт отсутствует. (Первоначально я хотел конвертер в DLL в том же приложении и нуждался в другом пространстве имен для предотвращения столкновений между старыми/новыми версиями каждого класса.) Это оказалось проще, чем решения, которые потребуют обработки каждого (их много). Еще раз спасибо за предложения. – user20493

0

Вы можете найти DataContractSerializer и , чтобы быть более прощающими. XmlSerializer отлично подходит для любого формата XML. DataContract имеет еще несколько ограничений (например, он плохо работает с атрибутами), но должен по-прежнему отлично работать для вашего сценария.

Смежные вопросы