从 XSD 生成 DataContract

Posted

技术标签:

【中文标题】从 XSD 生成 DataContract【英文标题】:Generate DataContract from XSD 【发布时间】:2011-01-12 10:24:04 【问题描述】:

我希望能够从 XSD 文件生成DataContract,最好使用xsd.exe tool。在我的每个项目上自动生成 [DataContract][DataMember] 的最简单方法是什么?

或者有更好的方法吗?我试图避免每次更改和重新生成 XSD 文件时都必须重新创建数据协定。

【问题讨论】:

好的,我现在遇到另一个错误。 DownloadRequestItem 上的 maxOccurs 必须为 1 这是我的架构 elementFormDefault="qualified"> 您能否通过编辑来更新您的原始问题?将 XML 放入 cmets 真的很难阅读而且一团糟...... wcfBlue wscfblue.codeplex.com 【参考方案1】:

xsd.exe 工具早于 WCF,并且对 [DataContract][DataMember] 一无所知。如果您确实使用 xsd.exe,则必须切换 WCF 以使用 XmlSerializer 而不是其默认的 DataContractSerializer 来序列化数据协定。

xsd.exe 的 WCF 等效项是 svcutil.exe - 它有一个参数 /dconly,它仅从给定的 XSD 文件创建数据协定。这将为您生成一个 C# 或 VB.NET 文件,其中包含经过良好注释的数据协定。

用法:

svcutil.exe (name of your XSD).xsd /dconly

这将在您的目录中生成一个具有相同基本名称的 *.cs 文件。

根据我的经验,svcutil.exe 对其 XML 结构非常挑剔 - 因此,如果它向您发出大量警告和/或错误,请不要感到惊讶。

【讨论】:

谢谢 不知道有这个工具 对它的 XML 结构非常挑剔 - DCS 支持和不支持的内容记录在这里 msdn.microsoft.com/en-us/library/ms733112(v=vs.110).aspx【参考方案2】:

使用 svcutil.exe 代替 xsd.exe

如何使用? 转到开始菜单 --> Microsoft Visual Studio 2008 --> Visual Studio 工具 --> Visual Studio 2008 命令提示符

并更改您想要的目录或将目录更改为您的 xsd 在那里。

svcutil.exe /help 

它将列出所有选项。

我用来生成数据合同的选项之一是

svcutil.exe /target:code /n:*,[Your Company and Department].Common.DataTransferObjects /dataContractOnly /serializer:auto /importXmlTypes common.xsd /out:common.cs

继续编码,祝你有美好的一天!

【讨论】:

【参考方案3】:

首先来自 XSD 的 DataContracts!

这是现代方式和非常好的实践,但是,VS2010 对自动化的支持非常有限 为了它。因此,我坐下来编写了一个纯 msbuild 目标:不需要修改 proj 文件 并生成 .g.cs。您还可以通过在此文件中进行一些小调整来非常轻松地生成 VB 代码。

安装:复制代码并将其作为 GenerateDataContractsFromXSD.targets 文件保存到文件夹“C:\Program Files\MSBuild\4.0\Microsoft.Common.targets\ImportAfter”中。这使得 msbuild 每次启动时都会读取它,这同样适用于 VS2010。

用法:

重新启动 VS2010 并将 xsd 添加到您的项目中。 选择 XSD 文件并按 F4 以显示属性工具窗口。 将 Build Action 属性更改为包含值 GenerateDataContracts 使用 XSD 文件构建项目。它会生成第一个 .g.cs 文件。 在解决方案资源管理器中更改视图以显示文件系统上的所有文件。 在项目中包含新生成的文件。 添加对 System.Runtime.Serialization 程序集的引用。

享受吧。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- Inject into the sequence of targets in order to add a generated file to compile -->
  <PropertyGroup>
    <CoreCompileDependsOn>
      GenerateDataContractsFromXSD;
      $(CoreCompileDependsOn);
    </CoreCompileDependsOn>
  </PropertyGroup>

  <ItemGroup>
    <SvcUtilParam Include="/nologo" />
    <SvcUtilParam Include="/target:code" />
    <SvcUtilParam Include="/dataContractOnly" />
    <SvcUtilParam Include="/serializer:DataContractSerializer" />
    <SvcUtilParam Include="/language:csharp" />
    <SvcUtilParam Include="/enableDataBinding" />
    <SvcUtilParam Include="/serializable" />
    <SvcUtilParam Include="/internal" />
  </ItemGroup>

  <ItemGroup>
    <AvailableItemName Include="GenerateDataContracts">
      <Targets>GenerateDataContractsFromXSD</Targets>
    </AvailableItemName>
  </ItemGroup>

  <ItemDefinitionGroup>
    <GenerateDataContracts>
      <!-- Use the following options to pass serialization options to SVCUTIL -->
      <DataContractSchemaMapping>"/n:*,$(AssemblyName).Data"</DataContractSchemaMapping>
    </GenerateDataContracts>
  </ItemDefinitionGroup>

  <!-- Automated Data Contract Serialisation using the SvcUtil.Exe tool -->
  <!-- in order to make it automated you have to set the build tool in properties window to GenerateDataContracts -->
  <Target Name="GenerateDataContractsFromXSD"
          Inputs="@(GenerateDataContracts)"
          Outputs="%(GenerateDataContracts.RootDir)\%(GenerateDataContracts.Directory)%(GenerateDataContracts.Filename).g.cs">

    <ItemGroup>
      <DataContractItems Include="@(GenerateDataContracts -> '%(FullPath)')" Condition="'%(Extension)' == '.xsd'" />
    </ItemGroup>

    <PropertyGroup>
      <DataContractGeneratedFilePath>%(DataContractItems.RootDir)\%(DataContractItems.Directory)%(DataContractItems.Filename).g.cs</DataContractGeneratedFilePath>
      <DataContractGeneratedIdentifier>@(GenerateDataContracts -> '%(RelativeDir)')%(DataContractItems.Filename).g.cs</DataContractGeneratedIdentifier>
    </PropertyGroup>

    <GetFrameworkSdkPath>
        <Output TaskParameter="Path" PropertyName="WIN_SDK_PATH" />
    </GetFrameworkSdkPath>

    <Exec 
      Condition="'@(DataContractItems)' != ''"
      Command="attrib -r &quot;$(DataContractGeneratedFilePath)&quot;" />

    <Exec
      Condition="'@(DataContractItems)' != ''"
      Outputs="$(DataContractGeneratedFilePath)"
      Command="&quot;$(WIN_SDK_PATH)bin\SvcUtil.exe&quot; @(SvcUtilParam, ' ') @(GenerateDataContracts -> '%(DataContractSchemaMapping)') &quot;/out:$(DataContractGeneratedFilePath)&quot; &quot;%(DataContractItems.FullPath)&quot;" />

  </Target>

  <Target Name="GetCopyGenerateDataContractItems"
          AfterTargets="AssignTargetPaths">
    <ItemGroup>
      <DataContractItems Include="@(GenerateDataContracts -> '%(FullPath)')" Condition="'%(Extension)' == '.xsd'" />
    </ItemGroup>

    <AssignTargetPath Files="@(DataContractItems)" RootFolder="$(MSBuildProjectDirectory)">
      <Output TaskParameter="AssignedFiles" ItemName="ContentWithTargetPath" />
    </AssignTargetPath>

  </Target>

 </Project>

【讨论】:

你的解决方案很有趣,但是“C:\Program Files\MSBuild\4.0\Microsoft.Common.targets\ImportAfter”我没有在我的电脑上看到那个文件夹。 @Serge,假设是您使用 .NET4 和 VS2010 的 MSBuild,在这种情况下,只需创建缺少的文件夹并将目标文件保存在那里(msbuild internaly搜索此位置)。如果提供了适当的更改,此解决方案也可能适用于以前的 MSBuild 版本。【参考方案4】:

在 64 位机器上,您会在

中找到它
%systemdrive%\Program Files (x86)\MSBuild\<version you use>

在这种情况下:

%systemdrive%\Program Files (x86)\MSBuild\4.0\Microsoft.Common.Targets\ImportAfter\

【讨论】:

以上是关于从 XSD 生成 DataContract的主要内容,如果未能解决你的问题,请参考以下文章

从 XSD 文件生成 WSDL

Jackson:从 XSD 生成 Jackson 类

从 XSD 生成 PHP 类?

使用默认包名称和XSD名称空间从XSD生成Java类

从 .XSD 文件生成 Java 类...?

从 Visual Studio 中的类生成 XSD