Сериализация дерева объектов для передачи WCF в Silverlight с использованием IsReference = true - PullRequest
2 голосов
/ 17 декабря 2010

Я использую Silverlight 4, .NET 4.0.

У меня есть объект, который определен в общей библиотеке (общей для моего проекта Silverlight и веб-проекта, в котором размещается служба WCF)

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

т.е.

class TreeNode
{
  public List<TreeNode> Children {get; set;}
  public TreeNode Root { get; set; }
  public TreeNode Parent { get; set; }
}

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

[DataContract(IsReference = true)]
class TreeNode
{
  public List<TreeNode> Children {get; set;}
  public TreeNode Root { get; set; }
  public TreeNode Parent { get; set; }
}

Проблема в том, что когда я это делаю, моя служба WCF больше не работает, так как не может загрузить необходимуюсборка для этого:

"Не удалось загрузить файл или сборку" System.Runtime.Serialization, Version = 2.0.5.0 "

Это связано с тем, что проект, содержащий класс TreeNode, построен на Silverlightсреда выполнения, а не среда .NET и использует System.Runtime.Serialization v2.0.5.0, а веб-проект и служба WCF используют v4.0.30319.

Итак, мой вопрос: существует ли способ, которыйЯ могу получить сериализацию этого объекта при сохранении ссылок без перемещения всей структуры объекта в другой проект, который создается в соответствии со стандартной средой выполнения .NET 4.0?

Кроме того, стоит отметить, что я пытался использовать условную компиляцию, такую ​​как:

#if SILVERLIGHT
[DataContract(IsReference = true)]
#endif

Но это не работает, так как служба WCF должна знать, что должна сохранять ссылки ...

Gочень признателен за любую помощь в этом.

1 Ответ

6 голосов
/ 17 декабря 2010

Для этого сценария я использовал три параметра:

  1. Прокси
  2. Не делиться сборкой, а делиться кодом.
  3. Ссылка наSystem.

2 - самый простой.Сохраните DataContract с IsReference = true.Создайте еще один проект, ориентированный на .NET (другой нацеленный на SL).В проекте .NET добавьте ваши файлы как связанные файлы.Таким образом, при компиляции SL будет использовать dll System.Runtime.Serialization для SL, а проект .NET будет использовать dll System.Runtime.Serialization для .NET.

1 и 3 позволяютдля совместного использования фактической DLL.

Вариант 1 работает следующим образом: Удалите атрибут DataContract.Перед сериализацией по проводам динамически создайте типы прокси, которые соответствуют вашим классам, которые вы хотите сериализовать (но добавьте атрибут DataContract с IsReference = true).Вы можете создавать эти классы, используя Reflection.Emit (или какой-либо другой динамический конструктор типов, например, Windsor).Затем используйте что-то вроде AutoMapper для копирования ваших данных в типы прокси.Сериализация / десериализация проксируемых типов.

Вариант 3 работает следующим образом: оставьте свой код таким, как он есть сейчас (с DataContract и IsReference = true).Установите System.Runtime.Serialization для копирования локальных.При желании добавьте задачу пост-сборки ILMerge с параметром / internalize, чтобы объединить dll System.Runtime.Serialization с вашим собственным.

...