Partilhar via


Ferramenta Contract-First

Muitas vezes, é necessário criar contratos de serviços a partir de serviços existentes. No .NET Framework 4.5 e posterior, as classes de contrato de dados podem ser criadas automaticamente a partir de serviços existentes usando a ferramenta contract-first. Para usar a ferramenta contract-first, o arquivo de definição de esquema XML (XSD) deve ser baixado localmente; a ferramenta não pode importar contratos de dados remotos via HTTP.

A ferramenta contract-first é integrada ao Visual Studio 2012 como uma tarefa de compilação. Os arquivos de código gerados pela tarefa de compilação são criados sempre que o projeto é construído, para que o projeto possa facilmente adotar alterações no contrato de serviço subjacente.

Os tipos de esquema que a ferramenta contract-first pode importar incluem o seguinte:

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

Tipos simples não serão gerados se forem primitivos como Int16 ou String; tipos complexos não serão gerados se forem do tipo Collection. Os tipos também não serão gerados se fizerem parte de outro xsd:complexType. Em todos esses casos, os tipos serão referenciados aos tipos existentes no projeto.

Adicionar um contrato de dados a um projeto

Antes que a ferramenta contract-first possa ser usada, o contrato de serviço (XSD) deve ser adicionado ao projeto. Para efeitos da presente síntese, será utilizado o seguinte contrato para ilustrar as funções que iniciam o contrato. Esta definição de serviço é um pequeno subconjunto do contrato de serviço usado pela API de pesquisa do Bing.

<?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>

Para adicionar o contrato de serviço acima ao projeto, clique com o botão direito do mouse no projeto e selecione Adicionar novo.... Selecione Definição de esquema no painel WCF da caixa de diálogo Modelos e nomeie o novo arquivo como SampleContract.xsd. Copie e cole o código acima na visualização de código do novo arquivo.

Configurando opções de primeiro contrato

As opções de primeiro contrato podem ser configuradas no menu Propriedades de um projeto WCF. Para habilitar o desenvolvimento contratual primeiro, marque a caixa de seleção Habilitar XSD como linguagem de definição de tipo na página WCF da janela de propriedades do projeto.

Screenshot of the WCF Options with contract-first development enabled.

Para configurar propriedades avançadas, clique no botão Avançado.

Advanced Contract Code Generation Settings dialog box.

As seguintes configurações avançadas podem ser configuradas para geração de código a partir de contratos. As configurações só podem ser configuradas para todos os arquivos no projeto; As configurações não podem ser configuradas para arquivos individuais no momento.

  • Modo de serializador: essa configuração determina qual serializador é usado para ler arquivos de contrato de serviço. Quando o XML Serializer é selecionado, as opções Tipos de coleção e Tipos de reutilização são desabilitadas. Essas opções só se aplicam ao Data Contract Serializer.

  • Tipos de reutilização: esta configuração especifica quais bibliotecas são usadas para reutilização de tipos. Essa configuração só se aplica se o Modo Serializador estiver definido como Serializador de Contrato de Dados.

  • Tipo de Coleção: Esta configuração especifica o tipo totalmente qualificado ou qualificado para montagem a ser usado para o tipo de dados de coleta. Essa configuração só se aplica se o Modo Serializador estiver definido como Serializador de Contrato de Dados.

  • Tipo de dicionário: esta configuração especifica o tipo totalmente qualificado ou qualificado para montagem a ser usado para o tipo de dados do dicionário.

  • EnableDataBinding: Esta configuração especifica se a interface deve ser implementada em todos os tipos de dados para implementar a INotifyPropertyChanged vinculação de dados.

  • ExcludedTypes:Esta configuração especifica a lista de tipos totalmente qualificados ou qualificados para montagem a serem excluídos dos assemblies referenciados. Essa configuração só se aplica se o Modo Serializador estiver definido como Serializador de Contrato de Dados.

  • GenerateInternalTypes: Esta configuração especifica se as classes marcadas como internas devem ser geradas. Essa configuração só se aplica se o Modo Serializador estiver definido como Serializador de Contrato de Dados.

  • GenerateSerializableTypes: Esta configuração especifica se as classes com o SerializableAttribute atributo devem ser geradas. Essa configuração só se aplica se o Modo Serializador estiver definido como Serializador de Contrato de Dados.

  • ImportXMLTypes: Esta configuração especifica se o serializador de contrato de dados deve ser configurado para aplicar o SerializableAttribute atributo a classes sem o DataContractAttribute atributo. Essa configuração só se aplica se o Modo Serializador estiver definido como Serializador de Contrato de Dados.

  • SupportFx35TypedDataSets: Esta configuração especifica se deve fornecer funcionalidade adicional para conjuntos de dados tipados criados para o .NET Framework 3.5. Quando o Modo Serializador é definido como XML Serializer, a TypedDataSetSchemaImporterExtensionFx35 extensão será adicionada ao importador de esquema XML quando esse valor for definido como True. Quando o Modo Serializador é definido como Serializador de Contrato de Dados, o tipo DateTimeOffset será excluído das Referências quando esse valor for definido como False, para que um DateTimeOffset seja sempre gerado para versões mais antigas da estrutura.

  • InputXsdFiles: Esta configuração especifica a lista de arquivos de entrada. Cada arquivo deve conter um esquema XML válido.

  • Idioma: esta configuração especifica o idioma do código de contrato gerado. A configuração deve ser reconhecível por CodeDomProvider.

  • NamespaceMappings: Esta configuração especifica os mapeamentos dos namespaces de destino XSD para namespaces CLR. Cada mapeamento deve usar o seguinte formato:

    "Schema Namespace, CLR Namespace"
    

    O XML Serializer só aceita um mapeamento no seguinte formato:

    "*, CLR Namespace"
    
  • OutputDirectory: Esta configuração especifica o diretório onde os arquivos de código serão gerados.

As configurações serão usadas para gerar tipos de contrato de serviço a partir dos arquivos de contrato de serviço quando o projeto for criado.

Usando o desenvolvimento contratual primeiro

Depois de adicionar o contrato de serviço ao projeto e confirmar as configurações de compilação, crie o projeto pressionando F6. Os tipos definidos no contrato de serviços estarão então disponíveis para utilização no projeto.

Para usar os tipos definidos no contrato de serviço, adicione uma referência ao ContractTypes namespace atual:

using MyProjectNamespace.ContractTypes;

Os tipos definidos no contrato de serviços serão então resolúveis no projeto, como mostrado abaixo:

SearchRequest class showing in IntelliSense after typing the first few letters.

Os tipos gerados pela ferramenta são criados no arquivo GeneratedXSDTypes.cs. O arquivo é criado no diretório> do <projeto/obj/<build configuration>/XSDGeneratedCode/ diretório por padrão. O esquema de exemplo no início deste artigo é convertido da seguinte maneira:

//------------------------------------------------------------------------------
// <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,
    }
}

Erros e avisos

Os erros e avisos encontrados na análise do esquema XSD aparecerão como erros de compilação e avisos.

Herança de interface

Não é possível usar a herança de interface com o desenvolvimento contract-first; Isso é consistente com a maneira como as interfaces se comportam em outras operações. Para usar uma interface que herda uma interface base, use dois pontos de extremidade separados. O primeiro ponto de extremidade usa o contrato herdado e o segundo ponto de extremidade implementa a interface base.