Udostępnij przez


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 opartych na kontrakcie zostanie użyty następujący kontrakt. 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.

Zrzut ekranu przedstawiający opcje programu WCF z włączonym podejściem

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

Okno dialogowe zaawansowanych ustawień generowania kodu umowy.

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; Obecnie 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 w pełni kwalifikowany zestawowo typ, 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 typ w pełni kwalifikowany lub kwalifikowany zestawowo, który ma być używany jako typ 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 przez zestawy typów, które mają zostać wykluczone z przywoływanych 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 serializacji jest ustawiony na serializator XML, rozszerzenie zostanie dodane do importera schematu XML, gdy ta wartość jest ustawiona na True. Gdy tryb serializatora jest ustawiony na Serializator kontraktu danych, typ DateTimeOffset zostanie wykluczony z odwołań, jeśli ta wartość jest ustawiona na Fałsz, aby DateTimeOffset było zawsze generowane dla starszych wersji frameworka.

  • 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.

Rozwój oparty na kontrakcie

Po dodaniu kontraktu usługi do projektu i potwierdzeniu ustawień kompilacji skompiluj projekt, naciskając 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:

Klasa SearchRequest pojawia się w funkcji IntelliSense po wpisaniu pierwszych kilku liter.

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 w podejściu kontrakt-pierwszy; jest to zgodne ze sposobem, w jaki interfejsy zachowują się w innych operacjach. Aby użyć interfejsu, który dziedziczy z 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.