Udostępnij za pośrednictwem


Narzędzie Contract-First

Kontrakty usług często muszą być tworzone na podstawie istniejących usług. W programie .NET Framework 4.5 lub nowszym klasy kontraktów danych można tworzyć automatycznie na podstawie istniejących usług przy użyciu narzędzia contract-first. Aby użyć narzędzia contract-first, plik definicji schematu XML (XSD) musi być pobrany lokalnie; narzędzie nie może importować zdalnych kontraktów danych za pośrednictwem protokołu HTTP.

Narzędzie oparte na umowie jest zintegrowane z programem Visual Studio 2012 jako zadaniem kompilacji. Pliki kodu generowane przez zadanie kompilacji są tworzone za każdym razem, gdy projekt jest kompilowany, dzięki czemu projekt może łatwo przyjąć zmiany w bazowym kontrakcie usługi.

Typy schematów, które narzędzie contract-first może importować, obejmują następujące elementy:

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

Typy proste nie będą generowane, jeśli są typami pierwotnymi, takimi jak Int16 lub String; typy złożone nie zostaną wygenerowane, jeśli są Collectiontypu . Typy nie będą również generowane, jeśli są częścią innego xsd:complexTypeelementu . We wszystkich tych przypadkach typy będą odwoływać się do istniejących typów w projekcie.

Dodawanie kontraktu danych do projektu

Aby można było użyć narzędzia pierwszego kontraktu, należy dodać kontrakt usługi (XSD) do projektu. Na potrzeby tego przeglądu do zilustrowania funkcji kontraktu zostaną użyte następujące kontrakty. Ta definicja usługi jest małym podzbiorem kontraktu usługi używanego przez interfejs API wyszukiwania 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>

Aby dodać powyższy kontrakt usługi do projektu, kliknij prawym przyciskiem myszy projekt i wybierz polecenie Dodaj nowy.... Wybierz pozycję Definicja schematu w okienku WCF okna dialogowego Szablony i nadaj nowej nazwie plik SampleContract.xsd. Skopiuj i wklej powyższy kod do widoku kodu nowego pliku.

Konfigurowanie opcji pierwszego kontraktu

Opcje pierwszego kontraktu można skonfigurować w menu Właściwości projektu WCF. Aby włączyć programowanie na początku kontraktu, zaznacz pole wyboru Włącz XSD jako język definicji typu na stronie WCF okna właściwości projektu.

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

Aby skonfigurować właściwości zaawansowane, kliknij przycisk Zaawansowane.

Advanced Contract Code Generation Settings dialog box.

Następujące ustawienia zaawansowane można skonfigurować do generowania kodu z kontraktów. Ustawienia można skonfigurować tylko dla wszystkich plików w projekcie; w tej chwili nie można skonfigurować ustawień dla poszczególnych plików.

  • Tryb serializatora: to ustawienie określa, który serializator jest używany do odczytywania plików kontraktów usługi. Po wybraniu opcji Serializator XML opcje Typy kolekcji i Typy ponownego użycia są wyłączone. Te opcje dotyczą tylko serializatora kontraktu danych.

  • Ponowne użycie typów: to ustawienie określa, które biblioteki są używane do ponownego użycia typu. To ustawienie ma zastosowanie tylko wtedy, gdy tryb serializatora jest ustawiony na Serializator kontraktu danych.

  • Typ kolekcji: to ustawienie określa w pełni kwalifikowany lub kwalifikowany typ zestawu, który ma być używany dla typu danych kolekcji. To ustawienie ma zastosowanie tylko wtedy, gdy tryb serializatora jest ustawiony na Serializator kontraktu danych.

  • Typ słownika: to ustawienie określa w pełni kwalifikowany lub kwalifikowany typ zestawu, który ma być używany dla typu danych słownika.

  • EnableDataBinding: to ustawienie określa, czy zaimplementować interfejs na wszystkich typach danych w celu zaimplementowania INotifyPropertyChanged powiązania danych.

  • ExcludedTypes:To ustawienie określa listę w pełni kwalifikowanych lub kwalifikowanych zestawów typów, które mają zostać wykluczone z przywołynych zestawów. To ustawienie ma zastosowanie tylko wtedy, gdy tryb serializatora jest ustawiony na Serializator kontraktu danych.

  • GenerateInternalTypes: to ustawienie określa, czy mają być generowane klasy oznaczone jako wewnętrzne. To ustawienie ma zastosowanie tylko wtedy, gdy tryb serializatora jest ustawiony na Serializator kontraktu danych.

  • GenerateSerializableTypes: to ustawienie określa, czy mają być generowane klasy z atrybutem SerializableAttribute . To ustawienie ma zastosowanie tylko wtedy, gdy tryb serializatora jest ustawiony na Serializator kontraktu danych.

  • ImportXMLTypes: to ustawienie określa, czy skonfigurować serializator kontraktu danych, aby zastosować SerializableAttribute atrybut do klas bez atrybutu DataContractAttribute . To ustawienie ma zastosowanie tylko wtedy, gdy tryb serializatora jest ustawiony na Serializator kontraktu danych.

  • SupportFx35TypedDataSets: to ustawienie określa, czy zapewnić dodatkowe funkcje dla typowych zestawów danych utworzonych dla programu .NET Framework 3.5. Gdy tryb serializatora jest ustawiony na serializator XML, rozszerzenie zostanie dodane do importera schematu XML, TypedDataSetSchemaImporterExtensionFx35 gdy ta wartość jest ustawiona na True. Gdy tryb serializatora jest ustawiony na Serializator kontraktu danych, typ DateTimeOffset zostanie wykluczony z odwołań, gdy ta wartość jest ustawiona na Fałsz, dzięki czemu DateTimeOffset wartość jest zawsze generowana dla starszych wersji platformy.

  • InputXsdFiles: to ustawienie określa listę plików wejściowych. Każdy plik musi zawierać prawidłowy schemat XML.

  • Język: to ustawienie określa język wygenerowanego kodu kontraktu. Ustawienie musi być rozpoznawalne przez CodeDomProvider.

  • NamespaceMappings: to ustawienie określa mapowania z przestrzeni nazw docelowych XSD na przestrzenie nazw CLR. Każde mapowanie powinno mieć następujący format:

    "Schema Namespace, CLR Namespace"
    

    Serializator XML akceptuje tylko jedno mapowanie w następującym formacie:

    "*, CLR Namespace"
    
  • OutputDirectory: to ustawienie określa katalog, w którym będą generowane pliki kodu.

Ustawienia będą używane do generowania typów kontraktów usług na podstawie plików kontraktów usługi podczas kompilowania projektu.

Korzystanie z programowania w pierwszej kolejności kontraktu

Po dodaniu kontraktu usługi do projektu i potwierdzeniu ustawień kompilacji skompiluj projekt, naciskając klawisz F6. Typy zdefiniowane w kontrakcie usługi będą następnie dostępne do użycia w projekcie.

Aby użyć typów zdefiniowanych w kontrakcie usługi, dodaj odwołanie do ContractTypes w bieżącej przestrzeni nazw:

using MyProjectNamespace.ContractTypes;

Typy zdefiniowane w kontrakcie usługi będą następnie rozpoznawalne w projekcie, jak pokazano poniżej:

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

Typy generowane przez narzędzie są tworzone w pliku GeneratedXSDTypes.cs. Plik jest tworzony w <katalogu> projektu/obj/<build configuration>/XSDGeneratedCode/ katalogu domyślnie. Przykładowy schemat na początku tego artykułu jest konwertowany w następujący sposób:

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

Błędy i ostrzeżenia

Błędy i ostrzeżenia napotkane podczas analizowania schematu XSD będą wyświetlane jako błędy kompilacji i ostrzeżenia.

Dziedziczenie interfejsu

Nie można używać dziedziczenia interfejsu z tworzeniem kontraktów po raz pierwszy; jest to zgodne ze sposobem, w jaki interfejsy zachowują się w innych operacjach. Aby użyć interfejsu dziedziczonego interfejsu podstawowego, użyj dwóch oddzielnych punktów końcowych. Pierwszy punkt końcowy używa dziedziczonego kontraktu, a drugi punkt końcowy implementuje interfejs podstawowy.