2009-08-28 3 views
4

Я ищу способ сериализации POCO, который содержит некоторые свойства только для чтения. В некоторых поисках Google и StackOverflow, я видел следующие предложения:Сериализовать в XML - частные свойства

  • использования DataContractSerializer; или
  • SoapFormatter или BinaryFormatter; или
  • замените мои свойства readonly на свойства чтения/записи;

Мои классы очень просты, они выглядят как:

public class MyClass 
{ 
    public int Id { get; private set; } 
    public string Name { get; private set; } 
    public MyClass(int id, string name) 
    { 
     Id = id; 
     Name = name; 
    } 
} 

Итак,

  • Я не хочу, чтобы мои свойства чтения/записи. Если они доступны только для чтения, это связано с тем, что моя модель домена запрашивает свойства только для чтения. Из-за этого модель домена не может измениться.
  • Я не хочу использовать DataContractSerializer, так как это загрязнило бы мою модель домена сериализацией.
  • BinaryFormatter не очень хороший вариант, в результате получается byte[], и я хотел бы рассматривать его как string (и я не хочу иметь дело с Encondings и так же, когда Deserializing мой объект).

То, что я действительно хотел бы это класс XmlSerializer способен сериализации только для чтения свойства.

Знаете ли вы, что такое такая реализация? Или любое другое удобное решение?

Спасибо!

ответ

4

Ну, обычно XmlSerializer не может сериализовать свойства только для чтения ... однако есть возможность сериализации свойств с внутренним набором: вам нужно сгенерировать сборку XML-сериализации и объявить ее как сборку «друг» используя атрибут InternalsVisibleTo. Вы можете автоматизировать этот процесс, добавив следующий код в ваш файл проекта:

<Target Name="AfterBuild" 
      DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" 
      Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)" 
      Outputs="$(OutputPath)$(_SGenDllName)"> 
    <SGen BuildAssemblyName="$(TargetFileName)" 
      BuildAssemblyPath="$(OutputPath)" 
      References="@(ReferencePath)" 
      ShouldGenerateSerializer="true" 
      UseProxyTypes="false" 
      KeyContainer="$(KeyContainerName)" 
      KeyFile="$(KeyOriginatorFile)" 
      DelaySign="$(DelaySign)" 
      ToolPath="$(SGenToolPath)"> 
     <Output TaskParameter="SerializationAssembly" 
       ItemName="SerializationAssembly" /> 
    </SGen> 
    </Target> 

И в AssemblyInfo.cs:

[assembly: InternalsVisibleTo("MyAssembly.XmlSerializers")] 

Конечно, вы не хотите свойства иметь внутренний набор, но если вы это сделаете, решение выше должно работать.

+0

Не должны ли внутренние видимые объекты System.Xml.Serialization? –

+3

Вот что я думал в первый раз, когда я пытался это сделать ... однако, сборка, которая фактически выполняет сериализацию (de), не является System.Xml, это определенная сборка сериализации. Обычно эта сборка динамически генерируется XmlSerializer во время выполнения со случайным именем (поэтому вы не можете использовать его с InternalsVisibleTo), но вы можете предварительно сгенерировать его с помощью инструмента командной строки sgen.exe или задачи сборки SGen. В этом случае сборка сериализации будет называться * YourAssemblyName * .XmlSerializers –

+0

Очень интересно. Я бы никогда об этом не подумал. Однако я хотел бы сохранить свои свойства с частными сеттерами. Merci! –

1

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

Но есть еще один вариант решения архитектуры. НЕ разрушить ваши требования бизнеса домена, а не разделите слои, похожие на аа дизайн nTeir и реализовать DTO в ...

Если вы разделите ваш бизнес, datafacade/dataadaptor (заводская модель хорошо подходит здесь) и слои DATAACCESS в 3-х проектов вы можете контролировать, ссылаясь на то, что бизнес никогда не знает о ваших DTO. Если вы решили удалить или реализовать сериализацию или обменять ее на сохранение на SQL-сервер, вы ни на что не повлияли бы на своем бизнес-уровне.

Существует всегда один падение, есть куча больше кода, чтобы написать: * Вы должны написать объект конвертора в обоих направлениях для каждого объекта, который вы хотите перейти к DATAACCESS * вы потенциально уничтожить некоторые из OO тайника sinse a. Сохраненный метод в бизнесе должен быть переведен на правильный тип в Dataface, прежде чем переходить к доступу к данным.

Вы можете сделать это намного проще с чем-то вроде nHybinate или аналогичным. Cheers Choco