2010-01-08 3 views
8

Мой архив имеет List<Student>, List<Course> и List<Enrolment> где Зачисление имеет Enrolment.Student и Enrolment.Course, которые являются ссылки один из студентов или курсов в двух предыдущих списках..NET XmlSerializer и несколько ссылок на тот же объект

Когда я использую XmlSerializer в своем репозитории, он выводит избыточные данные, поскольку он сериализует все свойства каждого учащегося в List<Student>, а затем снова для каждой ссылки на тех же учащихся в List<Enrolment>. Я ищу элегантный способ решить эту проблему.

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

Один из способов исправить избыточный выход - это XmlIgnore Enrolment.Student и Enrolment.Course и создать еще два свойства для сериализации - Enrolment.StudentID и Enrolment.CourseID. Однако во время десериализации ссылки для Enrolment.Student и Enrolment.Course не могут быть установлены (AFAIK), поскольку результаты десериализации List<Student> и List<Course> недоступны.

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

Другим методом будет XmlIgnore List<Enrolment> и создать вспомогательный класс сериализации регистрации, который инициализирует List<Enrolment> после завершения десериализации. Это похоже на много усилий.

Как другие люди сериализуют/десериализуют несколько ссылок на один и тот же объект с помощью XmlSerializer?

ответ

3

Ох боли сериализации: -> ...

Там никогда не было общее решение для этого, я думаю, именно поэтому MS раздели его из Silverlight рамок.

Я никогда не полагаюсь на какие-либо автоматические механизмы сериализации структуры .net. Для моих моделей и репозиториев я обычно знаю или могу легко программно определить, какие свойства являются простыми скалярными (номера/строки/и т. Д.) И которые являются ссылками на другие объекты (а также списки).

Есть в основном 2 сценария:

1: Мы хотим, чтобы сериализовать/передачу только плоскую информацию объектов. В этом случае я переношу только соответствующие идентификаторы для свойств, которые ссылаются на другие объекты. Затем получатель может выполнять последующие запросы, чтобы получить все остальные объекты, в которых они нуждаются.

2: Мы хотим передать как можно больше информации, т. Е. Более глубокие вложенные XML с несколькими уровнями, в основном для некоторых функций отчетности, отображающих все непосредственно, используя только некоторый CSS в XML. В этом случае на самом деле желательно, чтобы объекты, которые являются одинаковыми, будут разрешаться несколько раз в дереве XML.

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

+0

Очень успокаивающе - Будучи новым, я предполагал, что мне что-то не хватает. Поскольку моя проблема относится к вашему первому сценарию, я буду следовать вашему предложению построить что-то в базе кода, чтобы привести в порядок десериализацию. Возможно, я создам IXmlFinalizeDeserialization, которая может быть вызвана во всех моих объектах, отслеживая тех, чья десериализация неадекватна и исправляет ссылки. –

2

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

Лучшее, что вы можете сделать, это сериализовать пул объектов отдельно от их ссылок. Затем вы можете воссоздать свои списки после десериализации.

Кстати, знаете ли вы, что XmlSerializer не относится к C#?

+0

Thanks John - очень красноречиво. Я удалил C# из своих тегов. –

2

Вы можете реализовать интерфейс IXmlSerializable к Зачисление и в методе WriteXml генерации студентов и курса XML, который будет содержать только ключи т.д .:

<Student Id="5"/> 
<Course Id="6"/> 

и в методе ReadXml вы можете загрузить ссылки из этого. Вы также должны установить атрибут XmlIgnore для свойства Student и Course.

+0

Проблема с этим подходом заключается в том, что во время ReadXml вы не можете загружать ссылки (AFAIK) в другие данные, также десериализованные, поскольку они недоступны, пока десериализация не будет завершена. Знаете ли вы об этом? –

0

Как это звучит как решение:

  1. XmlIgnore каждый вторичный ссылка т.е. Enrolment.Student & Enrolment.Course
  2. создать свойство для каждого вторичного ссылки, который используется для сериализации/десериализуем внешний ключ вместо этой ссылки - префикс с XML_FK. например XML_FK_Student & XML_FK_Course
  3. Создать метод XML_FinalizeDeserialization, который вызывается после десериализации, чтобы загрузить ссылки, используя эти иностранные ключевые свойства.
+1

Было бы неплохо, если бы мы могли создать атрибут [XmlSecondary], который мы поставили перед ссылкой, которая заставляет XML_Serializer проверять ссылку на поля с префиксом [XMLPK] и выводить их только? Возможное? –

+0

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

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