协定优先工具

通常需要从现有服务创建服务协定。 在 .NET Framework 4.5 及更高版本中,可以使用协定优先工具从现有服务自动创建数据协定类。 若要使用协定优先工具,必须在本地下载 XML 架构定义文件 (XSD);该工具无法通过 HTTP 导入远程数据协定。

合同优先工具作为生成任务集成到 Visual Studio 2012 中。 每次生成项目时都会创建生成任务生成的代码文件,以便项目可以轻松采用基础服务协定中的更改。

合约优先工具可以导入的模式类型包括:

<xsd:complexType>
 <xsd:simpleType>
 </xsd:simpleType>
</xsd:complexType>

如果简单类型是基元类型,Int16String则不会生成简单类型;如果它们属于类型Collection,则不会生成复杂类型。 如果它们是另一 xsd:complexType 的组成部分,则也不会生成类型。 在所有这些情况下,这些类型将会被引用到项目中的现有类型。

向项目添加数据协定

在使用协定优先工具之前,必须将服务协定 (XSD) 添加到项目中。 为了本概述的目的,以下合约将被用来演示“以合约为先”的功能。 此服务定义是必应搜索 API 使用的服务协定的一小部分。

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="ServiceSchema"
    targetNamespace="http://tempuri.org/ServiceSchema.xsd"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/ServiceSchema.xsd"
    xmlns:mstns="http://tempuri.org/ServiceSchema.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:complexType name="SearchRequest">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="Version" type="xs:string" default="2.2" />
      <xs:element minOccurs="0" maxOccurs="1" name="Market" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" name="UILanguage" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="Query" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="AppId" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" name="Latitude" type="xs:double" />
      <xs:element minOccurs="0" maxOccurs="1" name="Longitude" type="xs:double" />
      <xs:element minOccurs="0" maxOccurs="1" name="Radius" type="xs:double" />
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="WebSearchOption">
    <xs:restriction base="xs:string">
      <xs:enumeration value="DisableHostCollapsing" />
      <xs:enumeration value="DisableQueryAlterations" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

若要将上述服务协定添加到项目,请右键单击项目并选择“ 添加新...”。 从“模板”对话框的 WCF 窗格中选择“架构定义”,并将新文件命名为 SampleContract.xsd。 将上述代码复制并粘贴到新文件的代码视图中。

配置协定优先选项

可以在 WCF 项目的“属性”菜单中配置协定优先选项。 若要启用协定优先开发,请在项目属性窗口的 WCF 页中选择“ 启用 XSD 作为类型定义语言 ”复选框。

启用了“契约优先开发”的 WCF 选项截图。

若要配置高级属性,请单击“高级”按钮。

“高级合同代码生成设置”对话框。

可以为合同中代码生成配置以下高级设置。 只能为项目中的所有文件配置设置;目前无法为单个文件配置设置。

  • 序列化程序模式:此设置确定用于读取服务协定文件的序列化程序。 选择 XML 序列化程序后,将禁用“集合类型和重用类型”选项。 这些选项仅适用于 数据协定序列化程序

  • 重用类型:此设置指定用于类型重用的库。 仅当 序列化程序模式 设置为 数据协定序列化程序时,此设置才适用。

  • 集合类型:此设置指定要用于集合数据类型的完全限定或程序集限定的类型。 仅当 序列化程序模式 设置为 数据协定序列化程序时,此设置才适用。

  • 字典类型:此设置指定要用于字典数据类型的完全限定或程序集限定的类型。

  • EnableDataBinding:此设置指定是否对所有数据类型实现 INotifyPropertyChanged 接口来实现数据绑定。

  • ExcludedTypes:此设置指定要从引用的程序集中排除的完全限定类型或程序集限定类型的列表。 仅当 序列化程序模式 设置为 数据协定序列化程序时,此设置才适用。

  • GenerateInternalTypes:此设置指定是否生成标记为内部的类。 仅当 序列化程序模式 设置为 数据协定序列化程序时,此设置才适用。

  • GenerateSerializableTypes:此设置指定是否使用 SerializableAttribute 特性生成类。 仅当 序列化程序模式 设置为 数据协定序列化程序时,此设置才适用。

  • ImportXMLTypes:此设置指定是否配置数据协定序列化程序,以将SerializableAttribute属性应用于没有DataContractAttribute属性的类。 仅当 序列化程序模式 设置为 数据协定序列化程序时,此设置才适用。

  • SupportFx35TypedDataSets:此设置指定是否为为 .NET Framework 3.5 创建的类型化数据集提供其他功能。 当 序列化程序模式 设置为 XML 序列化程序时,当此值设置为 True 时,扩展 TypedDataSetSchemaImporterExtensionFx35 将添加到 XML 架构导入程序。 当 序列化程序模式 设置为 数据协定序列化程序时,当此值设置为 False 时,将从引用中排除该类型 DateTimeOffset ,以便始终为较旧的框架版本生成一个 DateTimeOffset 类型。

  • InputXsdFiles:此设置指定输入文件的列表。 每个文件必须包含有效的 XML 架构。

  • 语言:此设置指定生成的协定代码的语言。 该设置必须为 CodeDomProvider 所识别。

  • NamespaceMappings:此设置指定从 XSD 目标命名空间到 CLR 命名空间的映射。 每个映射都应使用以下格式:

    "Schema Namespace, CLR Namespace"
    

    XML 序列化程序仅接受以下格式的一个映射:

    "*, CLR Namespace"
    
  • OutputDirectory:此设置指定将生成代码文件的目录。

生成项目时,这些设置将用于从服务协定文件生成服务协定类型。

使用协定优先开发

将服务协定添加到项目并确认生成设置后,按 F6 生成项目。 然后,服务协定中定义的类型将可用于项目中。

若要使用服务协定中定义的类型,请添加对当前命名空间下的引用 ContractTypes

using MyProjectNamespace.ContractTypes;

然后,服务合同中定义的类型将在项目中可解析,如下所示:

在键入前几个字母后,IntelliSense 会显示 SearchRequest 类。

该工具生成的类型在GeneratedXSDTypes.cs文件中创建。 默认情况下, <该文件在项目目录>/obj/<build configuration>/XSDGeneratedCode/ 目录中创建。 本文开头的示例架构将按如下所示进行转换:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.17330
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace TestXSD3.ContractTypes
{
    using System.Xml.Serialization;

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.17330")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/ServiceSchema.xsd")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/ServiceSchema.xsd", IsNullable=true)]
    public partial class SearchRequest
    {

        private string versionField;

        private string marketField;

        private string uILanguageField;

        private string queryField;

        private string appIdField;

        private double latitudeField;

        private bool latitudeFieldSpecified;

        private double longitudeField;

        private bool longitudeFieldSpecified;

        private double radiusField;

        private bool radiusFieldSpecified;

        public SearchRequest()
        {
            this.versionField = "2.2";
        }

        /// <remarks/>
        [System.ComponentModel.DefaultValueAttribute("2.2")]
        public string Version
        {
            get
            {
                return this.versionField;
            }
            set
            {
                this.versionField = value;
            }
        }

        /// <remarks/>
        public string Market
        {
            get
            {
                return this.marketField;
            }
            set
            {
                this.marketField = value;
            }
        }

        /// <remarks/>
        public string UILanguage
        {
            get
            {
                return this.uILanguageField;
            }
            set
            {
                this.uILanguageField = value;
            }
        }

        /// <remarks/>
        public string Query
        {
            get
            {
                return this.queryField;
            }
            set
            {
                this.queryField = value;
            }
        }

        /// <remarks/>
        public string AppId
        {
            get
            {
                return this.appIdField;
            }
            set
            {
                this.appIdField = value;
            }
        }

        /// <remarks/>
        public double Latitude
        {
            get
            {
                return this.latitudeField;
            }
            set
            {
                this.latitudeField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlIgnoreAttribute()]
        public bool LatitudeSpecified
        {
            get
            {
                return this.latitudeFieldSpecified;
            }
            set
            {
                this.latitudeFieldSpecified = value;
            }
        }

        /// <remarks/>
        public double Longitude
        {
            get
            {
                return this.longitudeField;
            }
            set
            {
                this.longitudeField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlIgnoreAttribute()]
        public bool LongitudeSpecified
        {
            get
            {
                return this.longitudeFieldSpecified;
            }
            set
            {
                this.longitudeFieldSpecified = value;
            }
        }

        /// <remarks/>
        public double Radius
        {
            get
            {
                return this.radiusField;
            }
            set
            {
                this.radiusField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlIgnoreAttribute()]
        public bool RadiusSpecified
        {
            get
            {
                return this.radiusFieldSpecified;
            }
            set
            {
                this.radiusFieldSpecified = value;
            }
        }
    }

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.17330")]
    [System.SerializableAttribute()]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/ServiceSchema.xsd")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/ServiceSchema.xsd", IsNullable=false)]
    public enum WebSearchOption
    {

        /// <remarks/>
        DisableHostCollapsing,

        /// <remarks/>
        DisableQueryAlterations,
    }
}

错误和警告

分析 XSD 架构时遇到的错误和警告将显示为生成错误和警告。

接口继承

接口继承不能用于协定优先开发;这与接口在其他操作中的行为方式一致。 若要使用继承基接口的接口,请使用两个单独的终结点。 第一终结点使用继承的协定,第二终结点实现基接口。