Генерация DataContract из XSD

Я хочу иметь возможность генерировать DataContract из файла XSD, предпочтительно используя инструмент xsd.exe. Как проще всего автоматически сгенерировать [DataContract] и [DataMember] для каждого из моих элементов?

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


person Daveo    schedule 03.02.2010    source источник
comment
Хорошо, теперь я получаю другую ошибку. maxOccurs on DownloadRequestItem должен быть равен 1. Это моя схема elementFormDefault=qualified› ‹xs:имя элемента=DownloadRequest› ‹xs:complexType› ‹xs:sequence› ‹xs:имя элемента=тип UserID=xs:string nillable=false maxOccurs=unbounded /› ‹xs:имя элемента=DownloadRequestItem nillable=true› ‹xs:complexType› ‹xs:sequence› ‹xs:имя элемента=FileID type=xs:string /› ‹/xs:sequence› ‹/xs:complexType› ‹ /xs:элемент› ‹/xs:последовательность› ‹/xs:complexType› ‹/xs:элемент› ‹/xs:схема›   -  person Daveo    schedule 04.02.2010
comment
не могли бы вы обновить исходный вопрос, отредактировав его ?? Вставлять XML в комментарии ОЧЕНЬ ОЧЕНЬ трудно читать и беспорядок.....   -  person marc_s    schedule 02.07.2010
comment
wcfBlue wscfblue.codeplex.com   -  person    schedule 19.10.2010


Ответы (4)


Инструмент 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-структурам, так что не удивляйтесь, если он выдаст вам массу предупреждений и/или ошибок.

person marc_s    schedule 03.02.2010
comment
Спасибо, я не знал, что этот инструмент существует - person Daveo; 04.02.2010
comment
довольно требовательна к своим XML-структурам — что DCS поддерживает, а что нет, описано здесь msdn.microsoft.com/en-us/library/ms733112(v=vs.110).aspx - person tom redfern; 20.01.2016

Используйте 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

Продолжайте кодить, добрый день!

person zakirhas7    schedule 29.11.2010

Сначала DataContracts из XSD!

Это современный способ и очень хорошая практика, однако 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>
person pavelz    schedule 08.03.2012
comment
Ваше решение интересно, но C:\Program Files\MSBuild\4.0\Microsoft.Common.targets\ImportAfter я не вижу эту папку на своем компьютере. - person Serge; 23.11.2012
comment
@Serge, предполагается, что вы используете MSBuild .NET4 и VS2010, в этом случае просто создайте недостающую папку (папки) и сохраните там целевой файл (msbuild выполняет внутренний поиск в этом месте). Это решение может работать и с предыдущей версией MSBuild, если были внесены соответствующие изменения. - person pavelz; 29.11.2012

На 64-битной машине вы найдете его в

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

В этом случае:

%systemdrive%\Program Files (x86)\MSBuild\4.0\Microsoft.Common.Targets\ImportAfter\
person Jacques Mostert    schedule 15.09.2014