C # Замок ActiveRecord: как элегантно (XML) сериализовать объекты ActiveRecord? - PullRequest
1 голос
/ 08 октября 2009

Мне трудно найти информацию о том, как элегантно сериализовать объекты ActiveRecord.

Мы хотели бы использовать XML в качестве формата, поскольку нам нужно выводить наши объекты таким образом, чтобы другая программа могла их реально проанализировать.

XML-сериализация обычно очень проста и проста в реализации, но проблема возникает при попытке сериализации объекта, возвращенного из базы данных ActiveRecord. База данных возвращает прокси-класс объекта, тип которого нельзя предвидеть явно с помощью атрибута [XmlInclude].

Например:

public class Foo : ActiveRecordLinqBase<Foo>
{
   public virtual string Bar{get;set;}

   public virtual int FooId{get;set;}

   public Foo(string bar)
   {
      Bar = bar;
   }

   public static void FooSerializeExample()
   {
      Foo tehFoozor = new Foo("omgFoo!");
      tehFoozor.SaveAndFlush();
      int id = tehFoozor.FooId;

      //...
      //Assume new ActiveRecord session.

      XmlSerializer serializer = new XmlSerializer(typeof(Foo));

      Foo tehFoozorToSerialize = Foo.Find(id);

      using(Stream stream = File.OpenWrite("tehFoozor.xml"))
      {
         serializer.Serialize(stream, tehFoozorToSerialize); //Will fail
      }
   }
}

При сериализации здесь мы получим сообщение:
«Тип FooProxy2e2de24df9be42909d13a67fdb00b981 не ожидался. Используйте атрибут XmlInclude или SoapInclude, чтобы указать типы, которые статически неизвестны.»

где тип Proxy будет совершенно непредсказуемым (по крайней мере, насколько мне известно).

В качестве временного решения моя команда поместила свойства каждого объекта AR в интерфейсы. Затем мы реализовали объекты «Контейнер» для каждого из них, которые по сути являются версиями объектов, не относящимися к AR, в формате XML. Учитывая тот факт, что в настоящее время у нас есть 18 различных объектов AR, которые сериализуются, это 36 дополнительных файлов в нашем решении! Что-то (все) говорит мне, что это плохое решение, но я не смог найти лучшего пути.

Мы также пытались использовать средство форматирования мыла, но поскольку ActiveRecrodLinqBase <> не «помечен как сериализуемый», это также был тупик.

Ответы [ 2 ]

3 голосов
/ 09 октября 2009

С нетерпением извлекайте все, что вам нужно, затем используйте AutoMapper , чтобы сопоставить его с DTO и сериализовать эти DTO.

Ошибка прокси, которую вы получаете, предполагает, что ваши DTO на самом деле используют прокси-коллекции NHibernate, тогда как вместо них они должны использовать простые List<T> или массивы. Убедитесь, что вы используете ToList() или аналогичный.

Кроме того, вам не нужно использовать интерфейсы для сопоставления DTO.

0 голосов
/ 09 октября 2009

Попробуйте DataContractSerializer.

Его эквивалентом [XmlInclude] является [KnownType], который включает версию, которая может динамически предоставлять тип для включения при первом отображении типа. Смотри http://msdn.microsoft.com/en-us/library/ms730167.aspx

Кроме того, я думаю (хотя и не уверен на 100%), что .NET4.0 будет включать в DataContractSerializer функцию «Тип сопоставления», которая специально упрощает подобные сценарии.

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

...