从XSD生成DataContract

27
我希望能够使用xsd.exe工具从XSD文件中生成一个DataContract。有什么简单的方法可以自动在每个项上生成[DataContract][DataMember]吗?
或者有更好的方法吗?我试图避免每次更改和重新生成XSD文件时都要重新创建数据合同。

好的,我现在又遇到了一个错误。DownloadRequestItem 上的 maxOccurs 必须为 1。这是我的模式: <xs:schema elementFormDefault="qualified"> <xs:element name="DownloadRequest"> xs:complexType xs:sequence <xs:element name="UserID" type="xs:string" nillable="false" maxOccurs="unbounded"/> <xs:element name="DownloadRequestItem" nillable="true"> xs:complexType xs:sequence <xs:element name="FileID" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> - Daveo
你能否通过编辑更新你的原始问题?在注释中放置XML真的非常难以阅读和混乱..... - marc_s
wcfBlue http://wscfblue.codeplex.com/ - user480631
4个回答

44
xsd.exe工具早于WCF,不了解[DataContract][DataMember]。如果您使用xsd.exe,则必须将WCF切换到使用XmlSerializer而不是其默认的DataContractSerializer来序列化数据合同。
WCF中与xsd.exe等效的工具是svcutil.exe - 它有一个参数/dconly,仅从给定的XSD文件中创建数据契约。这将为您生成一个C#或VB.NET文件,其中包含了精美注释的数据契约。
用法:
svcutil.exe (name of your XSD).xsd /dconly

这将会在你的目录下生成一个与原文件同名的*.cs文件。

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


谢谢,我不知道这个工具的存在。 - Daveo
非常挑剔于其XML结构 - DCS支持和不支持的内容在此处有所记录:https://msdn.microsoft.com/zh-cn/library/ms733112(v=vs.110).aspx - tom redfern

13

使用svcutil.exe替代xsd.exe

如何使用? 打开开始菜单 --> Microsoft Visual Studio 2008 --> Visual Studio Tools --> 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,以显示属性工具窗口。
  • 更改生成操作属性的值为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
1
@Serge,假设您使用的是.NET4和VS2010的MSBuild,在这种情况下,只需创建缺失的文件夹并将目标文件保存在那里(msbuild内部搜索此位置)。如果提供了适当的更改,则此解决方案也可能适用于以前的MSBuild版本。 - pavelz

1
在一台64位机器上,您会发现它在

中。

%systemdrive%\Program Files (x86)\MSBuild\<version you use>

在这种情况下:
%systemdrive%\Program Files (x86)\MSBuild\4.0\Microsoft.Common.Targets\ImportAfter\

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接