Condividi tramite


Strumento Contract-First

I contratti di servizio spesso devono essere creati da servizi esistenti. In .NET Framework 4.5 e versioni successive, le classi di contratto dati possono essere create automaticamente dai servizi esistenti usando lo strumento contract-first. Per usare lo strumento contract-first, è necessario scaricare localmente il file xsd (XML Schema Definition File). lo strumento non può importare contratti dati remoti tramite HTTP.

Lo strumento contract-first è integrato in Visual Studio 2012 come attività di compilazione. I file di codice generati dall'attività di compilazione vengono creati ogni volta che viene compilato il progetto, in modo che il progetto possa adottare facilmente le modifiche nel contratto di servizio sottostante.

I tipi di schema che lo strumento contract-first può importare includono quanto segue:

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

I tipi semplici non verranno generati se sono primitive, Int16 ad esempio o String. I tipi complessi non verranno generati se sono di tipo Collection. I tipi non verranno generati se fanno parte di un altro xsd:complexType oggetto. In tutti questi casi, i tipi verranno invece referenziati ai tipi esistenti nel progetto.

Aggiunta di un contratto di dati a un progetto

Prima di poter usare lo strumento contract-first, è necessario aggiungere il contratto di servizio (XSD) al progetto. Ai fini di questa panoramica, il contratto seguente verrà utilizzato per illustrare le funzioni contract-first. Questa definizione di servizio è un piccolo subset del contratto di servizio usato dall'API di ricerca di 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>

Per aggiungere il contratto di servizio precedente al progetto, fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi nuovo. Selezionare Definizione schema nel riquadro WCF della finestra di dialogo Modelli e assegnare al nuovo file il nome SampleContract.xsd. Copiare e incollare il codice precedente nella visualizzazione codice del nuovo file.

Configurazione delle opzioni contract-first

Le opzioni contract-first possono essere configurate nel menu Proprietà di un progetto WCF. Per abilitare lo sviluppo contract-first, selezionare la casella di controllo Abilita XSD come Type Definition Language nella pagina WCF della finestra delle proprietà del progetto.

Screenshot delle opzioni WCF con sviluppo con approccio contract-first abilitato.

Per configurare le proprietà avanzate, fare clic sul pulsante Avanzate.

Finestra di dialogo delle impostazioni avanzate per la generazione del codice di contratto.

Le impostazioni avanzate seguenti possono essere configurate per la generazione di codice dai contratti. Le impostazioni possono essere configurate solo per tutti i file nel progetto; Non è possibile configurare le impostazioni per singoli file al momento.

  • Modalità serializzatore: questa impostazione determina quale serializzatore viene usato per la lettura dei file del contratto di servizio. Quando si seleziona Serializzatore XML , le opzioni Tipi di raccolta e Riutilizzo tipi sono disabilitate. Queste opzioni si applicano solo al serializzatore del contratto dati.

  • Riutilizza tipi: questa impostazione specifica le librerie usate per il riutilizzo dei tipi. Questa impostazione si applica solo se la modalità serializzatore è impostata su Serializzatore contratto dati.

  • Tipo di raccolta: questa impostazione specifica il tipo completamente qualificato o qualificato dall'assembly da utilizzare per il tipo di dati della raccolta. Questa impostazione si applica solo se la modalità serializzatore è impostata su Serializzatore contratto dati.

  • Tipo dizionario: questa impostazione specifica il tipo completamente qualificato o qualificato dall'assembly da usare per il tipo di dati dizionario.

  • EnableDataBinding: questa impostazione specifica se implementare l'interfaccia in tutti i tipi di dati per implementare il INotifyPropertyChanged data binding.

  • ExcludedTypes: Questa impostazione specifica l'elenco di tipi qualificati completamente o qualificati da assembly da escludere dai riferimenti agli assembly. Questa impostazione si applica solo se la modalità serializzatore è impostata su Serializzatore contratto dati.

  • GenerateInternalTypes: questa impostazione specifica se generare classi contrassegnate come interne. Questa impostazione si applica solo se la modalità serializzatore è impostata su Serializzatore contratto dati.

  • GenerateSerializableTypes: questa impostazione specifica se generare classi con l'attributo SerializableAttribute . Questa impostazione si applica solo se la modalità serializzatore è impostata su Serializzatore contratto dati.

  • ImportXMLTypes: questa impostazione specifica se configurare il serializzatore del contratto dati per applicare l'attributo SerializableAttribute alle classi senza l'attributo DataContractAttribute . Questa impostazione si applica solo se la modalità serializzatore è impostata su Serializzatore contratto dati.

  • SupportFx35TypedDataSets: questa impostazione specifica se fornire funzionalità aggiuntive per i set di dati tipizzato creati per .NET Framework 3.5. Quando la modalità serializzatore è impostata su Serializzatore XML, l'estensione TypedDataSetSchemaImporterExtensionFx35 verrà aggiunta all'utilità di importazione di XML Schema quando questo valore è impostato su True. Quando la modalità Serializzatore è impostata su Serializzatore di contratto dati, il tipo DateTimeOffset sarà escluso dai Riferimenti quando questo valore è impostato su False, in modo che venga sempre generato un DateTimeOffset per le versioni precedenti del framework.

  • InputXsdFiles: questa impostazione specifica l'elenco dei file di input. Ogni file deve contenere un XML Schema valido.

  • Lingua: questa impostazione specifica la lingua del codice del contratto generato. L'impostazione deve essere riconoscibile da CodeDomProvider.

  • NamespaceMappings: questa impostazione specifica i mapping dagli spazi dei nomi di destinazione XSD agli spazi dei nomi CLR. Ogni mapping deve usare il formato seguente:

    "Schema Namespace, CLR Namespace"
    

    Il serializzatore XML accetta un solo mapping nel formato seguente:

    "*, CLR Namespace"
    
  • OutputDirectory: questa impostazione specifica la directory in cui verranno generati i file di codice.

Le impostazioni verranno usate per generare i tipi di contratto di servizio dai file del contratto di servizio al momento della compilazione del progetto.

Sviluppo orientato al contratto

Dopo aver aggiunto il contratto di servizio al progetto e aver confermato le impostazioni di compilazione, compilare il progetto premendo F6. I tipi definiti nel contratto di servizio saranno quindi disponibili per l'uso nel progetto.

Per usare i tipi definiti nel contratto di servizio, aggiungere un riferimento a ContractTypes nello spazio dei nomi corrente:

using MyProjectNamespace.ContractTypes;

I tipi definiti nel contratto di servizio saranno quindi risolvibili nel progetto, come illustrato di seguito:

Classe SearchRequest visualizzata in IntelliSense dopo aver digitato le prime lettere.

I tipi generati dallo strumento vengono creati nel file GeneratedXSDTypes.cs. Il file viene creato nella <directory> del progetto/obj/<build configuration>/XSDGeneratedCode/ directory per impostazione predefinita. Lo schema di esempio all'inizio di questo articolo viene convertito come segue:

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

Errori e avvisi

Gli errori e gli avvisi rilevati nell'analisi dello schema XSD verranno visualizzati come errori di compilazione e avvisi.

Ereditarietà dell'interfaccia

Non è possibile usare l'ereditarietà dell'interfaccia con lo sviluppo contract-first; questo comportamento è coerente con il comportamento delle interfacce in altre operazioni. Per usare un'interfaccia che eredita un'interfaccia di base, usare due endpoint separati. Il primo endpoint usa il contratto ereditato e il secondo endpoint implementa l'interfaccia di base.