【问题标题】:Serialize to XML - private properties序列化为 XML - 私有属性
【发布时间】:2009-08-28 13:49:14
【问题描述】:

我正在寻找一种方法来序列化包含一些只读属性的 POCO。在一些 Google 和 StackOverflow 搜索中,我看到了以下建议:

  • 使用DataContractSerializer;或
  • 使用 SoapFormatterBinaryFormatter;或
  • 读/写属性替换我的只读属性;

我的类很简单,它们看起来像:

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 等)。

我真正想要的是一个能够序列化只读属性的 XmlSerializer 类

你知道任何这样的实现吗?或者其他方便的解决方案?

谢谢!

【问题讨论】:

    标签: .net xml-serialization poco


    【解决方案1】:

    好吧,通常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")]
    

    当然,您可能不希望属性具有内部集,但如果这样做,上述解决方案应该可以工作。

    【讨论】:

    • 不应该是对 System.Xml.Serialization 可见的内部吗?
    • 这就是我第一次尝试这样做时的想法……但是,实际执行(反)序列化的程序集不是 System.Xml,它是一个特定的序列化程序集。通常这个程序集是由 XmlSerializer 在运行时动态生成的,具有随机名称(因此您不能将其与 InternalsVisibleTo 一起使用),但您可以使用 sgen.exe 命令行工具或 SGen 构建任务预先生成它。在这种情况下,序列化程序集将命名为 YourAssemblyName.XmlSerializers
    • 非常有趣。我永远不会想到这一点。但是,我想将我的财产保留给私人二传手。谢谢!
    • @marc_s :我认为这不是简单问题,而是依赖问题:将 [DataMember] 属性放在属性上会在业务域中引入对 DataContractSerializer 的依赖
    • 你看过 Marc Gravell 的“proto-buf”吗? code.google.com/p/protobuf-net 不确定它是否可以处理私有字段,但它是一个单独的、可扩展的序列化机制。
    【解决方案2】:

    虽然不幸的是,如果 serialize 可以访问私有属性,截至今天,这将是一件好事,但没有简单的方法。

    但架构解决方案还有另一种选择。 不要破坏您的业务领域需求,而是像 nTeir 设计那样分离您的层并实现 DTO...

    如果您将您的业务、datafacade/dataadaptor(工厂模式非常适合这里)和 DataAccess 层分离为 3 个项目,您可以通过引用该业务从不知道您的 DTO 来进行控制。 因此,如果您决定删除或实施序列化或将其交换为保存到 SQL Server,您不会影响业务层中的任何内容。

    总会有一个失败,还有一大堆代码要写: * 您必须为每个要访问 Dataaccess 的实体双向编写对象转换器 * 您可能会破坏一些隐藏的 OO

    您可以使用 nHybinate 或类似的东西让这一切变得更容易。 干杯 巧克力

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-20
      • 1970-01-01
      • 2013-01-28
      相关资源
      最近更新 更多