Surogaty kontraktu danych

Surogat kontraktu danych to zaawansowana funkcja oparta na modelu kontraktu danych. Ta funkcja jest przeznaczona do dostosowywania i zastępowania typów w sytuacjach, w których użytkownicy chcą zmienić sposób serializacji, deserializacji lub projekcji typu na metadane. W niektórych scenariuszach, w których może być używany zastępca, jest to, że kontrakt danych nie został określony dla typu, pola i właściwości nie są oznaczone atrybutem DataMemberAttribute lub użytkownicy chcą dynamicznie tworzyć odmian schematu.

Serializacja i deserializację są realizowane przy użyciu DataContractSerializer zastępczego kontraktu danych w celu konwersji z programu .NET Framework na odpowiedni format, na przykład XML. Za pomocą zastępczego kontraktu danych można również modyfikować metadane eksportowane dla typów podczas tworzenia reprezentacji metadanych, takich jak dokumenty schematu XML (XSD). Po zaimportowaniu kod jest tworzony na podstawie metadanych, a w tym przypadku można go użyć do dostosowania wygenerowanego kodu.

Jak działa surogat

Surogat działa przez mapowanie jednego typu (typ "oryginalny") na inny typ (typ "zastępczy"). W poniższym przykładzie przedstawiono oryginalny typ Inventory i nowy typ zastępczy InventorySurrogated . Typ Inventory nie można serializować, ale InventorySurrogated typ to:

public class Inventory
{
    public int pencils;
    public int pens;
    public int paper;
}

Ponieważ dla tej klasy nie zdefiniowano kontraktu danych, przekonwertuj klasę na klasę zastępczą z kontraktem danych. W poniższym przykładzie pokazano klasę zastępczą:

[DataContract(Name = "Inventory")]
public class InventorySurrogated
{
    [DataMember]
    public int numpencils;
    [DataMember]
    public int numpaper;
    [DataMember]
    private int numpens;

    public int pens
    {
        get { return numpens; }
        set { numpens = value; }
    }
}

Implementowanie elementu IDataContractSurrogate

Aby użyć zastępczego kontraktu danych, zaimplementuj IDataContractSurrogate interfejs.

Poniżej przedstawiono omówienie każdej metody IDataContractSurrogate z możliwą implementacją.

GetDataContractType

Metoda GetDataContractType mapuje jeden typ na inny. Ta metoda jest wymagana do serializacji, deserializacji, importowania i eksportowania.

Pierwsze zadanie definiuje typy mapowane na inne typy. Na przykład:

public Type GetDataContractType(Type type)
{
    Console.WriteLine("GetDataContractType");
    if (typeof(Inventory).IsAssignableFrom(type))
    {
        return typeof(InventorySurrogated);
    }
    return type;
}
  • Po serializacji mapowanie zwrócone przez tę metodę jest następnie używane do przekształcania oryginalnego wystąpienia w wystąpienie zastępcze przez wywołanie GetObjectToSerialize metody .

  • W przypadku deserializacji mapowanie zwrócone przez tę metodę jest używane przez serializator do deserializacji w wystąpieniu typu zastępczego. Następnie wywołuje GetDeserializedObject metodę przekształcenia wystąpienia zastępczego w wystąpienie oryginalnego typu.

  • W przypadku eksportu typ zastępczy zwracany przez tę metodę jest odzwierciedlany w celu uzyskania kontraktu danych do użycia do generowania metadanych.

  • Podczas importowania typ początkowy jest zmieniany na typ zastępczy, który jest odzwierciedlony w celu uzyskania kontraktu danych do użycia w celach, takich jak odwoływanie się do pomocy technicznej.

Parametr Type jest typem obiektu, który jest serializowany, deserializowany, importowany lub eksportowany. Metoda GetDataContractType musi zwracać typ danych wejściowych, jeśli zastępca nie obsługuje typu. W przeciwnym razie zwróć odpowiedni typ zastępczy. Jeśli istnieje kilka typów zastępczych, w tej metodzie można zdefiniować wiele mapowań.

Metoda nie jest wywoływana GetDataContractType dla wbudowanych elementów pierwotnych kontraktów danych, takich jak Int32 lub String. W przypadku innych typów, takich jak tablice, typy zdefiniowane przez użytkownika i inne struktury danych, ta metoda będzie wywoływana dla każdego typu.

W poprzednim przykładzie metoda sprawdza, czy type parametr i Inventory są porównywalne. Jeśli tak, metoda mapuje ją na InventorySurrogated. Za każdym razem, gdy jest wywoływana serializacja, deserializacja, schemat importu lub schemat eksportu, ta funkcja jest wywoływana jako pierwsza w celu określenia mapowania między typami.

GetObjectToSerialize, metoda

Metoda GetObjectToSerialize konwertuje oryginalne wystąpienie typu na wystąpienie typu zastępczego. Metoda jest wymagana do serializacji.

Następnym krokiem jest zdefiniowanie sposobu mapowania danych fizycznych z oryginalnego wystąpienia na zastępcę GetObjectToSerialize przez zaimplementowanie metody . Na przykład:

public object GetObjectToSerialize(object obj, Type targetType)
{
    Console.WriteLine("GetObjectToSerialize");
    if (obj is Inventory)
    {
        InventorySurrogated isur = new InventorySurrogated();
        isur.numpaper = ((Inventory)obj).paper;
        isur.numpencils = ((Inventory)obj).pencils;
        isur.pens = ((Inventory)obj).pens;
        return isur;
    }
    return obj;
}

Metoda jest wywoływana GetObjectToSerialize , gdy obiekt jest serializowany. Ta metoda transferuje dane z oryginalnego typu do pól typu zastępczego. Pola mogą być mapowane bezpośrednio na pola zastępcze lub manipulowanie oryginalnymi danymi mogą być przechowywane w surogatach. Niektóre możliwe zastosowania obejmują: bezpośrednie mapowanie pól, wykonywanie operacji na danych do przechowywania w polach zastępczych lub przechowywanie kodu XML oryginalnego typu w polu zastępczym.

Parametr targetType odnosi się do zadeklarowanego typu elementu członkowskiego. Ten parametr jest typem zastępczym zwracanym przez metodę GetDataContractType . Serializator nie wymusza przypisywania zwróconego obiektu do tego typu. Parametr obj jest obiektem do serializacji i zostanie przekonwertowany na jego zastępcę w razie potrzeby. Ta metoda musi zwrócić obiekt wejściowy, jeśli surogat nie obsługuje obiektu. W przeciwnym razie zostanie zwrócony nowy obiekt zastępczy. Zastępca nie jest wywoływany, jeśli obiekt ma wartość null. W ramach tej metody można zdefiniować wiele mapowań zastępczych dla różnych wystąpień.

Podczas tworzenia obiektu DataContractSerializermożna poinstruować go o zachowaniu odwołań do obiektów. (Aby uzyskać więcej informacji, zobacz Serializacja i deserializacja). W tym celu należy ustawić preserveObjectReferences parametr w konstruktorze na truewartość . W takim przypadku zastępca jest wywoływany tylko raz dla obiektu, ponieważ wszystkie kolejne serializacji po prostu zapisują odwołanie do strumienia. Jeśli preserveObjectReferences ustawiono falsewartość , zastępca jest wywoływany za każdym razem, gdy wystąpią wystąpienia.

Jeśli typ wystąpienia serializowane różni się od zadeklarowanego typu, informacje o typie są zapisywane w strumieniu, na przykład, xsi:type aby umożliwić deserializacji wystąpienia na drugim końcu. Ten proces występuje, czy obiekt jest zastępczy, czy nie.

Powyższy przykład konwertuje dane Inventory wystąpienia na InventorySurrogatedwartość . Sprawdza typ obiektu i wykonuje niezbędne manipulacje w celu przekonwertowania na typ zastępczy. W takim przypadku pola Inventory klasy są bezpośrednio kopiowane do InventorySurrogated pól klasy.

GetDeserializedObject, metoda

Metoda GetDeserializedObject konwertuje wystąpienie typu zastępczego na wystąpienie oryginalnego typu. Jest to wymagane do deserializacji.

Następnym zadaniem jest zdefiniowanie sposobu mapowania danych fizycznych z wystąpienia zastępczego na oryginalną. Na przykład:

public object GetDeserializedObject(object obj, Type targetType)
{
    Console.WriteLine("GetDeserializedObject");
    if (obj is InventorySurrogated)
    {
        Inventory invent = new Inventory();
        invent.pens = ((InventorySurrogated)obj).pens;
        invent.pencils = ((InventorySurrogated)obj).numpencils;
        invent.paper = ((InventorySurrogated)obj).numpaper;
        return invent;
    }
    return obj;
}

Ta metoda jest wywoływana tylko podczas deserializacji obiektu. Zapewnia odwrotne mapowanie danych na deserializacji z typu zastępczego z powrotem na jego oryginalny typ. Podobnie jak w GetObjectToSerialize przypadku metody, niektóre możliwe zastosowania mogą służyć do bezpośredniej wymiany danych pól, wykonywania operacji na danych i przechowywania danych XML. Podczas deserializacji nie zawsze można uzyskać dokładne wartości danych z oryginalnego z powodu manipulacji w konwersji danych.

Parametr targetType odnosi się do zadeklarowanego typu elementu członkowskiego. Ten parametr jest typem zastępczym zwracanym przez metodę GetDataContractType . Parametr obj odwołuje się do obiektu, który został zdeserializowany. Obiekt można przekonwertować z powrotem na oryginalny typ, jeśli jest on zastępczy. Ta metoda zwraca obiekt wejściowy, jeśli zastępca nie obsługuje obiektu. W przeciwnym razie obiekt deserializowany zostanie zwrócony po zakończeniu konwersji. Jeśli istnieje kilka typów zastępczych, możesz podać konwersję danych z zastępczego na typ podstawowy dla każdego z nich, wskazując każdy typ i jego konwersję.

Podczas zwracania obiektu tabele obiektów wewnętrznych są aktualizowane za pomocą obiektu zwróconego przez ten zastępca. Wszystkie kolejne odwołania do wystąpienia uzyskają wystąpienie zastępcze z tabel obiektów.

W poprzednim przykładzie obiekty typu InventorySurrogated są konwertowane z powrotem na typ Inventorypoczątkowy . W takim przypadku dane są przesyłane bezpośrednio z powrotem do InventorySurrogated odpowiednich pól w pliku Inventory. Ponieważ nie ma żadnych manipulacji danymi, każde z pól składowych będzie zawierać te same wartości co przed serializacji.

GetCustomDataToExport, metoda

Podczas eksportowania schematu metoda jest opcjonalna GetCustomDataToExport . Służy do wstawiania dodatkowych danych lub wskazówek do wyeksportowanego schematu. Dodatkowe dane można wstawić na poziomie elementu członkowskiego lub na poziomie typu. Na przykład:

public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
    Console.WriteLine("GetCustomDataToExport(Member)");
    System.Reflection.FieldInfo fieldInfo = (System.Reflection.FieldInfo)memberInfo;
    if (fieldInfo.IsPublic)
    {
        return "public";
    }
    else
    {
        return "private";
    }
}

Ta metoda (z dwoma przeciążeniami) umożliwia dołączenie dodatkowych informacji do metadanych na poziomie elementu członkowskiego lub typu. Istnieje możliwość uwzględnienia wskazówek dotyczących tego, czy element członkowski jest publiczny, czy prywatny, oraz komentarze, które byłyby zachowywane podczas eksportowania i importowania schematu. Takie informacje zostaną utracone bez tej metody. Ta metoda nie powoduje wstawiania lub usuwania elementów członkowskich lub typów, ale raczej dodaje dodatkowe dane do schematów na jednym z tych poziomów.

Metoda jest przeciążona i może przyjmować Type parametr (clrtype lub MemberInfo (memberInfo ). Drugi parametr jest zawsze parametrem Type (dataContractType ). Ta metoda jest wywoływana dla każdego elementu członkowskiego i typu typu zastępczego dataContractType .

Jeden z tych przeciążeń musi zwrócić albo null obiekt możliwy do serializacji. Obiekt inny niż null zostanie serializowany jako adnotacja do wyeksportowanego schematu. Type W przypadku przeciążenia każdy typ wyeksportowany do schematu jest wysyłany do tej metody w pierwszym parametrze wraz z typem zastępczym jako parametremdataContractType. MemberInfo W przypadku przeciążenia każdy element członkowski wyeksportowany do schematu wysyła informacje jako memberInfo parametr z typem zastępczym w drugim parametrze.

GetCustomDataToExport, metoda (typ, typ)

Metoda jest wywoływana podczas eksportowania IDataContractSurrogate.GetCustomDataToExport(Type, Type) schematu dla każdej definicji typu. Metoda dodaje informacje do typów w schemacie podczas eksportowania. Każdy zdefiniowany typ jest wysyłany do tej metody w celu określenia, czy istnieją jakieś dodatkowe dane, które należy uwzględnić w schemacie.

GetCustomDataToExport, metoda (MemberInfo, type)

Element jest wywoływany podczas eksportowania IDataContractSurrogate.GetCustomDataToExport(MemberInfo, Type) dla każdego elementu członkowskiego w eksportowanych typach. Ta funkcja umożliwia dostosowanie komentarzy do elementów członkowskich, które zostaną uwzględnione w schemacie podczas eksportowania. Informacje dotyczące każdego elementu członkowskiego w klasie są wysyłane do tej metody w celu sprawdzenia, czy w schemacie należy dodać jakiekolwiek dodatkowe dane.

W powyższym przykładzie przeszukuje dataContractType element dla każdego członka zastępczego. Następnie zwraca odpowiedni modyfikator dostępu dla każdego pola. Bez tego dostosowania domyślna wartość modyfikatorów dostępu jest publiczna. W związku z tym wszystkie elementy członkowskie będą zdefiniowane jako publiczne w kodzie wygenerowanym przy użyciu wyeksportowanego schematu niezależnie od tego, jakie są ich rzeczywiste ograniczenia dostępu. Jeśli ta implementacja nie jest używana, element członkowski numpens będzie publiczny w wyeksportowanym schemacie, mimo że został zdefiniowany w surogatce jako prywatny. Za pomocą tej metody w wyeksportowanym schemacie modyfikator dostępu można wygenerować jako prywatny.

GetReferencedTypeOnImport, metoda

Ta metoda mapuje Type surogat na oryginalny typ. Ta metoda jest opcjonalna w przypadku importu schematu.

Podczas tworzenia zastępczego, który importuje schemat i generuje dla niego kod, następnym zadaniem jest zdefiniowanie typu wystąpienia zastępczego do oryginalnego typu.

Jeśli wygenerowany kod musi odwoływać się do istniejącego typu użytkownika, jest to wykonywane przez zaimplementowanie GetReferencedTypeOnImport metody .

Podczas importowania schematu ta metoda jest wywoływana dla każdej deklaracji typu, aby zamapować kontrakt danych zastępczych na typ. Parametry typeName ciągu i typeNamespace zdefiniuj nazwę i przestrzeń nazw typu zastępczego. Wartość zwracana dla GetReferencedTypeOnImport elementu służy do określania, czy należy wygenerować nowy typ. Ta metoda musi zwrócić prawidłowy typ lub wartość null. W przypadku prawidłowych typów zwrócony typ będzie używany jako typ przywoływanego w wygenerowanym kodzie. Jeśli zostanie zwrócona wartość null, nie zostanie odwołany żaden typ i należy utworzyć nowy typ. Jeśli istnieje kilka zastępców, istnieje możliwość wykonania mapowania dla każdego typu zastępczego z powrotem do jego typu początkowego.

Parametr customData jest obiektem pierwotnie zwróconym z GetCustomDataToExport. Jest to customData używane, gdy autorzy zastępczy chcą wstawić dodatkowe dane/wskazówki do metadanych do użycia podczas importowania w celu wygenerowania kodu.

Process ImportType, metoda

Metoda ProcessImportedType dostosowuje dowolny typ utworzony na podstawie importu schematu. Ta metoda jest opcjonalna.

Podczas importowania schematu ta metoda umożliwia dostosowanie wszelkich importowanych informacji o typie i kompilacji. Na przykład:

public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
    Console.WriteLine("ProcessImportedType");
    foreach (CodeTypeMember member in typeDeclaration.Members)
    {
        object memberCustomData = member.UserData[typeof(IDataContractSurrogate)];
        if (memberCustomData != null
          && memberCustomData is string
          && ((string)memberCustomData == "private"))
        {
            member.Attributes = ((member.Attributes & ~MemberAttributes.AccessMask) | MemberAttributes.Private);
        }
    }
    return typeDeclaration;
}

Podczas importowania ta metoda jest wywoływana dla każdego wygenerowanego typu. Zmień określony CodeTypeDeclaration lub zmodyfikuj element CodeCompileUnit. Obejmuje to zmianę nazwy, elementów członkowskich, atrybutów i wielu innych właściwości obiektu CodeTypeDeclaration. Przetwarzając element CodeCompileUnit, można zmodyfikować dyrektywy, przestrzenie nazw, zestawy, do których się odwołujesz, oraz kilka innych aspektów.

Parametr CodeTypeDeclaration zawiera deklarację typu DOM kodu. Parametr CodeCompileUnit umożliwia modyfikację przetwarzania kodu. Zwracanie null wyników w deklaracji typu jest odrzucane. Z drugiej strony podczas zwracania CodeTypeDeclarationelementu modyfikacje są zachowywane.

Jeśli dane niestandardowe są wstawiane podczas eksportowania metadanych, należy przekazać je użytkownikowi podczas importowania, aby można było z niego korzystać. Te dane niestandardowe mogą służyć do programowania wskazówek dotyczących modelu lub innych komentarzy. Każde CodeTypeDeclaration wystąpienie zawiera CodeTypeMember dane niestandardowe jako UserData właściwość rzutowania na IDataContractSurrogate typ.

W powyższym przykładzie wprowadzono pewne zmiany w zaimportowaniu schematu. Kod zachowuje prywatne elementy członkowskie oryginalnego typu przy użyciu zastępcy. Domyślnym modyfikatorem dostępu podczas importowania schematu jest public. W związku z tym wszyscy członkowie schematu zastępczego będą publiczne, chyba że zostaną zmodyfikowane, tak jak w tym przykładzie. Podczas eksportowania dane niestandardowe są wstawiane do metadanych dotyczących elementów członkowskich, które są prywatne. Przykład wyszukuje dane niestandardowe, sprawdza, czy modyfikator dostępu jest prywatny, a następnie modyfikuje odpowiedni element członkowski, aby był prywatny, ustawiając jego atrybuty. Bez tego dostosowania element numpens członkowski zostanie zdefiniowany jako publiczny, a nie prywatny.

GetKnownCustomDataTypes, metoda

Ta metoda uzyskuje niestandardowe typy danych zdefiniowane ze schematu. Metoda jest opcjonalna dla importu schematu.

Metoda jest wywoływana na początku eksportowania i importowania schematu. Metoda zwraca niestandardowe typy danych używane w schemacie wyeksportowanym lub zaimportowanym. Metoda jest przekazywana Collection<T> ( customDataTypes parametr), który jest kolekcją typów. Metoda powinna dodać do tej kolekcji dodatkowe znane typy. Aby umożliwić serializacji i deserializacji danych niestandardowych przy użyciu elementu DataContractSerializer, potrzebne są znane niestandardowe typy danych. Aby uzyskać więcej informacji, zobacz Znane typy kontraktów danych.

Implementowanie zastępczego

Aby użyć zastępczego kontraktu danych w programie WCF, należy wykonać kilka specjalnych procedur.

Aby użyć zastępczego do serializacji i deserializacji

Użyj elementu , DataContractSerializer aby wykonać serializacji i deserializacji danych z surogatem. Element DataContractSerializer jest tworzony przez element DataContractSerializerOperationBehavior. Należy również określić zastępcę.

Aby zaimplementować serializacji i deserializacji
  1. Utwórz wystąpienie ServiceHost usługi . Aby uzyskać pełne instrukcje, zobacz Podstawowe programowanie WCF.

  2. Dla każdego ServiceEndpoint z określonego hosta usługi znajdź jego OperationDescription.

  3. Przeszukaj zachowania operacji, aby określić, czy znaleziono wystąpienie obiektu DataContractSerializerOperationBehavior .

  4. Jeśli element DataContractSerializerOperationBehavior zostanie znaleziony, ustaw jego DataContractSurrogate właściwość na nowe wystąpienie zastępczego. Jeśli nie DataContractSerializerOperationBehavior zostanie znalezione, utwórz nowe wystąpienie i ustaw DataContractSurrogate element członkowski nowego zachowania na nowe wystąpienie zastępczego.

  5. Na koniec dodaj to nowe zachowanie do bieżących zachowań operacji, jak pokazano w poniższym przykładzie:

    using (ServiceHost serviceHost = new ServiceHost(typeof(InventoryCheck)))
        foreach (ServiceEndpoint ep in serviceHost.Description.Endpoints)
        {
            foreach (OperationDescription op in ep.Contract.Operations)
            {
                DataContractSerializerOperationBehavior dataContractBehavior =
                    op.Behaviors.Find<DataContractSerializerOperationBehavior>()
                    as DataContractSerializerOperationBehavior;
                if (dataContractBehavior != null)
                {
                    dataContractBehavior.DataContractSurrogate = new InventorySurrogated();
                }
                else
                {
                    dataContractBehavior = new DataContractSerializerOperationBehavior(op);
                    dataContractBehavior.DataContractSurrogate = new InventorySurrogated();
                    op.Behaviors.Add(dataContractBehavior);
                }
            }
        }
    

Aby użyć zastępczego do importowania metadanych

Podczas importowania metadanych, takich jak WSDL i XSD w celu wygenerowania kodu po stronie klienta, zastępca musi zostać dodany do składnika odpowiedzialnego za generowanie kodu ze schematu XSD. XsdDataContractImporter W tym celu bezpośrednio zmodyfikuj metadane używane do importowania WsdlImporter metadanych.

Aby zaimplementować surogat do importowania metadanych
  1. Zaimportuj WsdlImporter metadane przy użyciu klasy .

  2. TryGetValue Użyj metody , aby sprawdzić, czy XsdDataContractImporter element został zdefiniowany.

  3. TryGetValue Jeśli metoda zwróci falsewartość , utwórz nową XsdDataContractImporter właściwość i ustaw jej Options właściwość na nowe wystąpienie ImportOptions klasy. W przeciwnym razie użyj importera zwróconego outTryGetValue przez parametr metody .

  4. Jeśli właściwość XsdDataContractImporter nie ImportOptions jest zdefiniowana, ustaw właściwość na nowe wystąpienie ImportOptions klasy.

  5. DataContractSurrogate Ustaw właściwość elementu na ImportOptionsXsdDataContractImporter nowe wystąpienie zastępcze.

  6. Dodaj element XsdDataContractImporter do kolekcji zwróconej State przez właściwość WsdlImporter klasy (dziedziczonej MetadataExporter z klasy).

  7. ImportAllContracts Użyj metody , WsdlImporter aby zaimportować wszystkie kontrakty danych w schemacie. W ostatnim kroku kod jest generowany na podstawie schematów załadowanych przez wywołanie do zastępczego.

    MetadataExchangeClient mexClient = new MetadataExchangeClient(metadataAddress);
    mexClient.ResolveMetadataReferences = true;
    MetadataSet metaDocs = mexClient.GetMetadata();
    WsdlImporter importer = new WsdlImporter(metaDocs);
    object dataContractImporter;
    XsdDataContractImporter xsdInventoryImporter;
    if (!importer.State.TryGetValue(typeof(XsdDataContractImporter),
        out dataContractImporter))
        xsdInventoryImporter = new XsdDataContractImporter();
    
    xsdInventoryImporter = (XsdDataContractImporter)dataContractImporter;
    xsdInventoryImporter.Options ??= new ImportOptions();
    xsdInventoryImporter.Options.DataContractSurrogate = new InventorySurrogated();
    importer.State.Add(typeof(XsdDataContractImporter), xsdInventoryImporter);
    
    Collection<ContractDescription> contracts = importer.ImportAllContracts();
    

Aby użyć zastępczego do eksportowania metadanych

Domyślnie podczas eksportowania metadanych z programu WCF dla usługi należy wygenerować schemat WSDL i XSD. Zastępca musi zostać dodany do składnika odpowiedzialnego za generowanie schematu XSD dla typów kontraktów danych, XsdDataContractExporter. W tym celu należy użyć zachowania, które implementuje modyfikowanie IWsdlExportExtension obiektu , lub bezpośrednie modyfikowanie WsdlExporterużywanego do eksportowania WsdlExporter metadanych.

Aby użyć zastępcy do eksportowania metadanych
  1. Utwórz nowy WsdlExporter lub użyj parametru przekazanego wsdlExporterExportContract do metody .

  2. Użyj funkcji , TryGetValue aby sprawdzić, czy XsdDataContractExporter element został zdefiniowany.

  3. Jeśli TryGetValue zwraca falsewartość , utwórz nową XsdDataContractExporter z wygenerowanymi schematami XML z WsdlExporterelementu i dodaj ją do kolekcji zwróconej przez State właściwość WsdlExporter. W przeciwnym razie użyj eksportera zwróconego outTryGetValue przez parametr metody .

  4. Jeśli właściwość XsdDataContractExporter nie ExportOptions jest zdefiniowana, ustaw Options właściwość na nowe wystąpienie ExportOptions klasy.

  5. DataContractSurrogate Ustaw właściwość elementu na ExportOptionsXsdDataContractExporter nowe wystąpienie zastępcze. Kolejne kroki eksportowania metadanych nie wymagają żadnych zmian.

    WsdlExporter exporter = new WsdlExporter();
    //or
    //public void ExportContract(WsdlExporter exporter,
    // WsdlContractConversionContext context) { ... }
    object dataContractExporter;
    XsdDataContractExporter xsdInventoryExporter;
    if (!exporter.State.TryGetValue(typeof(XsdDataContractExporter),
        out dataContractExporter))
    {
        xsdInventoryExporter = new XsdDataContractExporter(exporter.GeneratedXmlSchemas);
    }
    else
    {
        xsdInventoryExporter = (XsdDataContractExporter)dataContractExporter;
    }
    
    exporter.State.Add(typeof(XsdDataContractExporter), xsdInventoryExporter);
    
    if (xsdInventoryExporter.Options == null)
        xsdInventoryExporter.Options = new ExportOptions();
    xsdInventoryExporter.Options.DataContractSurrogate = new InventorySurrogated();
    

Zobacz też