Używanie klasy XmlSerializer

Program Windows Communication Foundation (WCF) może używać dwóch różnych technologii serializacji, aby przekształcić dane w aplikacji w kod XML przesyłany między klientami i usługami: DataContractSerializer i XmlSerializer.

DataContractSerializer

Domyślnie program WCF używa DataContractSerializer klasy do serializacji typów danych. Ten serializator obsługuje następujące typy:

  • Typy pierwotne (na przykład liczby całkowite, ciągi i tablice bajtów), a także niektóre specjalne typy, takie jak XmlElement i DateTime, które są traktowane jako typy pierwotne.

  • Typy kontraktów danych (typy oznaczone atrybutem DataContractAttribute ).

  • Typy oznaczone atrybutem SerializableAttribute , które obejmują typy implementujące ISerializable interfejs.

  • Typy implementujące IXmlSerializable interfejs.

  • Wiele typowych typów kolekcji, które obejmują wiele typów kolekcji ogólnych.

Wiele typów programu .NET Framework należy do dwóch ostatnich kategorii i dlatego można je serializować. Tablice typów możliwych do serializacji można również serializować. Aby uzyskać pełną listę, zobacz Określanie transferu danych w kontraktach usług.

Parametr DataContractSerializer, używany razem z typami kontraktów danych, jest zalecanym sposobem pisania nowych usług WCF. Aby uzyskać więcej informacji, zobacz Using Data Contracts (Korzystanie z kontraktów danych).

Xmlserializer

Program WCF obsługuje również klasę XmlSerializer . Klasa XmlSerializer nie jest unikatowa dla programu WCF. Jest to ten sam aparat serializacji, który ASP.NET usług sieci Web. Klasa XmlSerializer obsługuje znacznie węższy zestaw typów niż DataContractSerializer klasa, ale umożliwia znacznie większą kontrolę nad wynikowym kodem XML i obsługuje znacznie więcej standardu języka definicji schematu XML (XSD). Nie wymaga również żadnych atrybutów deklaratywnych w typach możliwych do serializacji. Aby uzyskać więcej informacji, zobacz temat Serializacja XML w dokumentacji programu .NET Framework. Klasa XmlSerializer nie obsługuje typów kontraktów danych.

W przypadku używania Svcutil.exe lub funkcji Dodaj odwołanie do usługi w programie Visual Studio w celu wygenerowania kodu klienta dla usługi innej firmy lub uzyskania dostępu do schematu innej firmy odpowiedni serializator jest automatycznie wybierany. Jeśli schemat nie jest zgodny z elementem DataContractSerializer, XmlSerializer zostanie wybrany element .

Przełącz się do elementu XmlSerializer

Czasami może być konieczne ręczne przełączenie na XmlSerializer. Dzieje się tak na przykład w następujących przypadkach:

  • Podczas migrowania aplikacji z usług sieci Web ASP.NET do programu WCF warto ponownie użyć istniejących typów zgodnych z XmlSerializerprogramem zamiast tworzenia nowych typów kontraktów danych.

  • Gdy dokładna kontrola nad plikiem XML wyświetlanym w komunikatach jest ważna, ale dokument WSDL (Web Services Description Language) nie jest dostępny, na przykład podczas tworzenia usługi z typami, które muszą być zgodne z określonym ustandaryzowanym, opublikowanym schematem, który nie jest zgodny z modułem DataContractSerializer.

  • Podczas tworzenia usług, które są zgodne ze starszym standardem kodowania SOAP.

W tych i innych przypadkach można ręcznie przełączyć się do XmlSerializer klasy, stosując XmlSerializerFormatAttribute atrybut do usługi, jak pokazano w poniższym kodzie.

[ServiceContract]
[XmlSerializerFormat]
public class BankingService
{
[OperationContract]
    public void ProcessTransaction(BankingTransaction bt)
    {
        // Code not shown.
    }
}

//BankingTransaction is not a data contract class,
//but is an XmlSerializer-compatible class instead.
public class BankingTransaction
{
    [XmlAttribute]
    public string Operation;
    [XmlElement]
    public Account fromAccount;
    [XmlElement]
    public Account toAccount;
    [XmlElement]
    public int amount;
}
//Notice that the Account class must also be XmlSerializer-compatible.
<ServiceContract(), XmlSerializerFormat()> _
Public Class BankingService
    <OperationContract()> _
    Public Sub ProcessTransaction(ByVal bt As BankingTransaction)
        ' Code not shown.
    End Sub
End Class


' BankingTransaction is not a data contract class,
' but is an XmlSerializer-compatible class instead.

Public Class BankingTransaction
    <XmlAttribute()> _
    Public Operation As String
    <XmlElement()> _
    Public fromAccount As Account
    <XmlElement()> _
    Public toAccount As Account
    <XmlElement()> _
    Public amount As Integer
End Class
'Notice that the Account class must also be XmlSerializer-compatible.

Zagadnienia związane z zabezpieczeniami

Uwaga

Podczas przełączania aparatów serializacji należy zachować ostrożność. W zależności od używanego serializatora ten sam typ może serializować kod XML w zależności od używanego serializatora. Jeśli przypadkowo użyjesz nieprawidłowego serializatora, możesz ujawnić informacje z typu, którego nie zamierzasz ujawniać.

Na przykład DataContractSerializer klasa serializuje tylko elementy członkowskie oznaczone atrybutem DataMemberAttribute podczas serializacji typów kontraktów danych. Klasa XmlSerializer serializuje dowolny element członkowski publiczny. Zobacz typ w poniższym kodzie.

[DataContract]
public class Customer
{
    [DataMember]
    public string firstName;
    [DataMember]
    public string lastName;
    public string creditCardNumber;
}
<DataContract()> _
Public Class Customer
    <DataMember()> _
    Public firstName As String
    <DataMember()> _
    Public lastName As String
    Public creditCardNumber As String
End Class

Jeśli typ jest przypadkowo używany w kontrakcie usługi, w którym XmlSerializer wybrano klasę, creditCardNumber składowa jest serializowana, co prawdopodobnie nie jest zamierzone.

Mimo że DataContractSerializer klasa jest domyślna, możesz jawnie wybrać ją dla usługi (chociaż nigdy nie należy tego robić), stosując DataContractFormatAttribute atrybut do typu kontraktu usługi.

Serializator używany dla usługi jest integralną częścią kontraktu i nie można go zmienić, wybierając inne powiązanie lub zmieniając inne ustawienia konfiguracji.

Inne ważne zagadnienia dotyczące zabezpieczeń mają zastosowanie do XmlSerializer klasy. Najpierw zdecydowanie zaleca się, aby każda aplikacja WCF korzystająca z klasy była podpisana przy użyciu XmlSerializer klucza chronionego przed ujawnieniem. To zalecenie ma zastosowanie zarówno w przypadku wykonania ręcznego przełącznika, XmlSerializer jak i wykonania przełącznika automatycznego (przez Svcutil.exe, dodawanie odwołania do usługi lub podobne narzędzie). Dzieje się tak, ponieważ XmlSerializer aparat serializacji obsługuje ładowanie wstępnie wygenerowanych zestawów serializacji, o ile są podpisane przy użyciu tego samego klucza co aplikacja. Aplikacja niepodpisana jest całkowicie niechroniona z możliwością złośliwego zestawu zgodnego z oczekiwaną nazwą wstępnie wygenerowanego zestawu serializacji umieszczonego w folderze aplikacji lub globalnej pamięci podręcznej zestawów. Oczywiście osoba atakująca musi najpierw uzyskać dostęp do zapisu w jednej z tych dwóch lokalizacji, aby podjąć próbę wykonania tej akcji.

Inne zagrożenie, które istnieje za każdym razem, gdy jest używane XmlSerializer , jest związane z dostępem do zapisu w folderze tymczasowym systemu. Aparat XmlSerializer serializacji tworzy i używa tymczasowych zestawów serializacji w tym folderze. Należy pamiętać, że każdy proces z dostępem do zapisu do folderu tymczasowego może zastąpić te zestawy serializacji złośliwym kodem.

Reguły obsługi elementu XmlSerializer

Nie można bezpośrednio stosować XmlSerializeratrybutów zgodnych z parametrami operacji kontraktu ani zwracać wartości. Można je jednak zastosować do wpisanych komunikatów (części treści kontraktu komunikatów), jak pokazano w poniższym kodzie.

[ServiceContract]
[XmlSerializerFormat]
public class BankingService
{
    [OperationContract]
    public void ProcessTransaction(BankingTransaction bt)
    {
        //Code not shown.
    }
}

[MessageContract]
public class BankingTransaction
{
    [MessageHeader]
    public string Operation;
    [XmlElement, MessageBodyMember]
    public Account fromAccount;
    [XmlElement, MessageBodyMember]
    public Account toAccount;
    [XmlAttribute, MessageBodyMember]
    public int amount;
}
<ServiceContract(), XmlSerializerFormat()> _
Public Class BankingService
    <OperationContract()> _
    Public Sub ProcessTransaction(ByVal bt As BankingTransaction)
        'Code not shown.
    End Sub
End Class

<MessageContract()> _
Public Class BankingTransaction
    <MessageHeader()> _
    Public Operation As String
    <XmlElement(), MessageBodyMember()> _
    Public fromAccount As Account
    <XmlElement(), MessageBodyMember()> _
    Public toAccount As Account
    <XmlAttribute(), MessageBodyMember()> _
    Public amount As Integer
End Class

Po zastosowaniu do wpisanych elementów członkowskich wiadomości te atrybuty zastępują właściwości powodujące konflikt atrybutów komunikatu wpisanego. Na przykład w poniższym kodzie ElementName zastępuje Namewartość .

    [MessageContract]
    public class BankingTransaction
    {
        [MessageHeader] public string Operation;

        //This element will be <fromAcct> and not <from>:
        [XmlElement(ElementName="fromAcct"), MessageBodyMember(Name="from")]
        public Account fromAccount;

        [XmlElement, MessageBodyMember]
        public Account toAccount;

        [XmlAttribute, MessageBodyMember]
        public int amount;
}
<MessageContract()> _
Public Class BankingTransaction
    <MessageHeader()> _
    Public Operation As String

    'This element will be <fromAcct> and not <from>:
    <XmlElement(ElementName:="fromAcct"), _
        MessageBodyMember(Name:="from")> _
    Public fromAccount As Account

    <XmlElement(), MessageBodyMember()> _
    Public toAccount As Account

    <XmlAttribute(), MessageBodyMember()> _
    Public amount As Integer
End Class

Atrybut MessageHeaderArrayAttribute nie jest obsługiwany w przypadku używania elementu XmlSerializer.

Uwaga

W takim przypadku XmlSerializer zgłaszany jest następujący wyjątek, który jest zwalniany przed usługą WCF: "Element zadeklarowany na najwyższym poziomie schematu nie może mieć maxOccurs> wartości 1. Podaj element otoki dla "więcej" przy użyciu XmlArray metody lub XmlArrayItem zamiast XmlElementAttribute, lub przy użyciu stylu opakowanego parametru."

Jeśli otrzymasz taki wyjątek, sprawdź, czy ta sytuacja ma zastosowanie.

Program WCF nie obsługuje SoapIncludeAttribute atrybutów i XmlIncludeAttribute w kontraktach komunikatów i kontraktach operacji; zamiast tego użyj atrybutu KnownTypeAttribute .

Typy implementujące interfejs IXmlSerializable

Typy implementujące IXmlSerializable interfejs są w pełni obsługiwane przez element DataContractSerializer. Atrybut XmlSchemaProviderAttribute powinien być zawsze stosowany do tych typów w celu kontrolowania ich schematu.

Ostrzeżenie

Jeśli serializacji typów polimorficznych należy zastosować XmlSchemaProviderAttribute do typu, aby upewnić się, że poprawny typ jest serializowany.

Istnieją trzy odmiany typów, które implementują IXmlSerializable: typy reprezentujące dowolną zawartość, typy reprezentujące pojedynczy element i starsze DataSet typy.

  • Typy zawartości używają metody dostawcy schematu XmlSchemaProviderAttribute określonej przez atrybut . Metoda nie zwraca null wartości , a IsAny właściwość atrybutu jest pozostawiona na wartości domyślnej false. Jest to najbardziej typowe użycie IXmlSerializable typów.

  • Typy elementów są używane, gdy typ musi kontrolować własną IXmlSerializable nazwę elementu głównego. Aby oznaczyć typ jako typ elementu, ustaw IsAny właściwość atrybutu XmlSchemaProviderAttribute na true wartość lub powrót null z metody dostawcy schematu. Posiadanie metody dostawcy schematu jest opcjonalne dla typów elementów — można określić null zamiast nazwy metody w pliku XmlSchemaProviderAttribute. Jeśli IsAny jednak określono true metodę dostawcy schematu, metoda musi zwrócić nullwartość .

  • Starsze DataSet typy to IXmlSerializable typy, które nie są oznaczone atrybutem XmlSchemaProviderAttribute . Zamiast tego polegają na metodzie generowania GetSchema schematu. Ten wzorzec jest używany dla DataSet typu i jego typizowanego zestawu danych pochodzi z klasy we wcześniejszych wersjach programu .NET Framework, ale jest teraz przestarzały i jest obsługiwany tylko ze starszych powodów. Nie należy polegać na tym wzorcu i zawsze stosować XmlSchemaProviderAttribute do typów IXmlSerializable .

Typy zawartości IXmlSerializable

Podczas serializacji elementu członkowskiego danych typu, który implementuje IXmlSerializable i jest typem zawartości zgodnie z definicją wcześniej, serializator zapisuje element otoki dla elementu członkowskiego danych i przekazuje kontrolę do WriteXml metody . Implementacja WriteXml może napisać dowolny kod XML, który obejmuje dodawanie atrybutów do elementu otoki. Po WriteXml zakończeniu serializator zamyka element.

Podczas deserializacji elementu danych typu, który implementuje IXmlSerializable i jest typem zawartości zgodnie z definicją wcześniej, deserializator umieszcza czytnik XML w elemencie otoki elementu elementu danych i przekazuje kontrolę do ReadXml metody. Metoda musi odczytać cały element, w tym tagi początkowe i końcowe. Upewnij się, że ReadXml kod obsługuje przypadek, w którym element jest pusty. ReadXml Ponadto implementacja nie powinna polegać na elemplecie otoki, który jest nazwany w określony sposób. Nazwa jest wybierana przez serializator może się różnić.

Dozwolone jest przypisywanie IXmlSerializable typów zawartości polimorficznie, na przykład do składowych danych typu Object. Dozwolone jest również, aby wystąpienia typu mogły mieć wartość null. Na koniec można używać IXmlSerializable typów z włączonym zachowywaniem grafu obiektów i parametrem NetDataContractSerializer. Wszystkie te funkcje wymagają serializatora WCF dołączania niektórych atrybutów do elementu otoki ("nil" i "type" w przestrzeni nazw wystąpienia schematu XML i "Id", "Ref", "Type" i "Assembly" w przestrzeni nazw specyficznej dla programu WCF).

Atrybuty do ignorowania podczas implementowania readxml

Przed przekazaniem kontrolki do ReadXml kodu deserializator sprawdza element XML, wykrywa te specjalne atrybuty XML i działa na nich. Jeśli na przykład wartość "nil" to true, wartość null jest deserializowana i ReadXml nie jest wywoływana. W przypadku wykrycia polimorfizmu zawartość elementu jest deserializowana tak, jakby była innym typem. Wywoływana jest implementacja typu przypisanego ReadXml polimorficznie. W każdym razie implementacja ReadXml powinna ignorować te atrybuty specjalne, ponieważ są obsługiwane przez deserializator.

Zagadnienia dotyczące schematu typów zawartości IXmlSerializable

Podczas eksportowania schematu i IXmlSerializable typu zawartości wywoływana jest metoda dostawcy schematu. Element XmlSchemaSet jest przekazywany do metody dostawcy schematu. Metoda może dodać dowolny prawidłowy schemat do zestawu schematów. Zestaw schematów zawiera schemat, który jest już znany w czasie eksportowania schematu. Gdy metoda dostawcy schematu musi dodać element do zestawu schematów, musi określić, czy element XmlSchema z odpowiednią przestrzenią nazw już istnieje w zestawie. Jeśli tak, metoda dostawcy schematu musi dodać nowy element do istniejącego XmlSchemaelementu . W przeciwnym razie musi utworzyć nowe XmlSchema wystąpienie. Jest to ważne, jeśli są używane tablice IXmlSerializable typów. Jeśli na przykład masz IXmlSerializable typ, który zostanie wyeksportowany jako typ "A" w przestrzeni nazw "B", możliwe, że w czasie, gdy metoda dostawcy schematu jest nazywana zestawem schematów, zawiera już schemat "B" do przechowywania typu "ArrayOfA".

Oprócz dodawania typów do klasy metoda dostawcy schematu XmlSchemaSetdla typów zawartości musi zwracać wartość inną niż null. Może zwrócić element XmlQualifiedName , który określa nazwę typu schematu, który ma być używany dla danego IXmlSerializable typu. Ta kwalifikowana nazwa służy również jako nazwa kontraktu danych i przestrzeń nazw dla typu. Dozwolone jest zwracanie typu, który nie istnieje w zestawie schematów natychmiast po powrocie metody dostawcy schematu. Oczekuje się jednak, że do czasu eksportowania wszystkich powiązanych typów ( Export metoda jest wywoływana dla wszystkich odpowiednich typów w XsdDataContractExporter obiekcie i Schemas dostęp do właściwości), typ istnieje w zestawie schematów. Uzyskanie dostępu do właściwości przed wykonaniem Schemas wszystkich odpowiednich Export wywołań może spowodować wystąpienie obiektu XmlSchemaException. Aby uzyskać więcej informacji na temat procesu eksportowania, zobacz Eksportowanie schematów z klas.

Metoda dostawcy schematu może również zwrócić XmlSchemaType wartość , która ma być używana. Typ może być anonimowy lub nie. Jeśli jest anonimowy, schemat typu IXmlSerializable jest eksportowany jako typ anonimowy za każdym razem, gdy IXmlSerializable typ jest używany jako element członkowski danych. Typ IXmlSerializable nadal ma nazwę kontraktu danych i przestrzeń nazw. (Jest to określane zgodnie z opisem w temacie Nazwy kontraktów danych z wyjątkiem tego, że DataContractAttribute atrybut nie może być używany do dostosowywania nazwy. Jeśli nie jest anonimowy, musi być jednym z typów w pliku XmlSchemaSet. Ten przypadek jest odpowiednikiem zwracania XmlQualifiedName typu .

Ponadto dla typu jest eksportowana deklaracja elementu globalnego. Jeśli typ nie ma zastosowanego atrybutu XmlRootAttribute , element ma taką samą nazwę i przestrzeń nazw jak kontrakt danych, a jego właściwość "nillable" to true. Jedynym wyjątkiem jest przestrzeń nazw schematu (http://www.w3.org/2001/XMLSchema) — jeśli kontrakt danych typu znajduje się w tej przestrzeni nazw, odpowiedni element globalny znajduje się w pustej przestrzeni nazw, ponieważ zabronione jest dodawanie nowych elementów do przestrzeni nazw schematu. Jeśli typ ma zastosowany atrybut, deklaracja elementu globalnego XmlRootAttribute jest eksportowana przy użyciu następujących właściwości: ElementNamei NamespaceIsNullable . Wartości domyślne XmlRootAttribute zastosowane to nazwa kontraktu danych, pusta przestrzeń nazw i wartość "nillable" to true.

Te same reguły deklaracji elementów globalnych mają zastosowanie do starszych typów zestawów danych. Należy pamiętać, że XmlRootAttribute nie można zastąpić deklaracji elementów globalnych dodanych za pomocą kodu niestandardowego, dodanego do XmlSchemaSet metody przy użyciu dostawcy schematu lub dla GetSchema starszych typów zestawów danych.

Typy elementów IXmlSerializable

IXmlSerializable typy elementów mają właściwość ustawioną IsAny na true lub mają zwracaną metodę nulldostawcy schematu .

Serializowanie i deserializacji typu elementu jest bardzo podobne do serializacji i deserializacji typu zawartości. Istnieją jednak pewne istotne różnice:

  • Oczekuje się, że implementacja WriteXml napisze dokładnie jeden element (który może oczywiście zawierać wiele elementów podrzędnych). Nie należy pisać atrybutów poza tym pojedynczym elementem, wieloma elementami równorzędnymi ani mieszaną zawartością. Element może być pusty.

  • Implementacja ReadXml nie powinna odczytywać elementu otoki. Oczekuje się, że odczytuje jeden element, który WriteXml generuje.

  • W przypadku regularnego serializacji typu elementu (na przykład jako elementu członkowskiego danych w kontrakcie danych) serializator generuje element otoki przed wywołaniem WriteXmlelementu , tak jak w przypadku typów zawartości. Jednak podczas serializacji typu elementu na najwyższym poziomie serializator zwykle nie generuje elementu otoki w ogóle wokół elementu, który WriteXml zapisuje, chyba że główna nazwa i przestrzeń nazw są jawnie określone podczas konstruowania serializatora w DataContractSerializer konstruktorach lub NetDataContractSerializer . Aby uzyskać więcej informacji, zobacz Serializacja i Deserializacja.

  • Podczas serializacji typu elementu na najwyższym poziomie bez określania nazwy głównej i przestrzeni nazw w czasie WriteStartObject budowy i WriteEndObject zasadniczo nic nie robić i WriteObjectContent wywołuje .WriteXml W tym trybie nie można null przypisać obiektu serializowanego i nie można go przypisać polimorficznie. Ponadto nie można włączyć zachowywania grafu obiektów i NetDataContractSerializer nie można go użyć.

  • Podczas deserializacji typu elementu na najwyższym poziomie bez określania nazwy głównej i przestrzeni nazw w czasie budowy zwraca true wartość , IsStartObject jeśli może znaleźć początek dowolnego elementu. ReadObject z parametrem ustawionym verifyObjectName na true zachowanie w taki sam sposób jak IsStartObject przed faktycznym odczytaniem obiektu. ReadObject następnie przekazuje kontrolę do ReadXml metody.

Schemat wyeksportowany dla typów elementów jest taki sam jak dla XmlElement typu opisanego we wcześniejszej sekcji, z tą różnicą, że metoda dostawcy schematu może dodać dowolny dodatkowy schemat do XmlSchemaSet typu zawartości. Używanie atrybutu XmlRootAttribute z typami elementów jest niedozwolone, a deklaracje elementów globalnych nigdy nie są emitowane dla tych typów.

Różnice w kodzie XmlSerializer

Interfejs IXmlSerializable i XmlSchemaProviderAttribute atrybuty są XmlRootAttribute również zrozumiałe przez XmlSerializer element . Istnieją jednak pewne różnice w sposobie ich traktowania w modelu kontraktu danych. Ważne różnice zostały podsumowane na poniższej liście:

  • Metoda dostawcy schematu musi być publiczna, aby była używana w elemecie XmlSerializer, ale nie musi być publiczna do użycia w modelu kontraktu danych.

  • Metoda dostawcy schematu jest wywoływana, gdy IsAny znajduje się true w modelu kontraktu danych, ale nie w przypadku elementu XmlSerializer.

  • XmlRootAttribute Jeśli atrybut nie jest obecny dla zawartości lub starszych typów zestawów danych, XmlSerializer eksportuje deklarację elementu globalnego w pustej przestrzeni nazw. W modelu kontraktu danych używana przestrzeń nazw jest zwykle przestrzenią nazw kontraktu danych zgodnie z wcześniejszym opisem.

Należy pamiętać o tych różnicach podczas tworzenia typów, które są używane z obu technologii serializacji.

Importowanie schematu IXmlSerializable

Podczas importowania schematu wygenerowanego na podstawie IXmlSerializable typów istnieje kilka możliwości:

  • Wygenerowany schemat może być prawidłowym schematem kontraktu danych, zgodnie z opisem w temacie Data Contract Schema Reference (Dokumentacja schematu kontraktu danych). W takim przypadku schemat można zaimportować jak zwykle, a zwykłe typy kontraktów danych są generowane.

  • Wygenerowany schemat może nie być prawidłowym schematem kontraktu danych. Na przykład metoda dostawcy schematu może wygenerować schemat, który obejmuje atrybuty XML, które nie są obsługiwane w modelu kontraktu danych. W takim przypadku można zaimportować schemat jako IXmlSerializable typy. Ten tryb importowania nie jest domyślnie włączony, ale można go łatwo włączyć — na przykład za pomocą /importXmlTypes przełącznika wiersza polecenia do narzędzia ServiceModel Metadata Tool (Svcutil.exe). Opisano to szczegółowo w temacie Importing Schema to Generate Classes (Importowanie schematu do generowania klas). Należy pamiętać, że musisz pracować bezpośrednio z kodem XML dla wystąpień typu. Możesz również rozważyć użycie innej technologii serializacji, która obsługuje szerszy zakres schematów — zobacz temat dotyczący korzystania z programu XmlSerializer.

  • Możesz chcieć ponownie użyć istniejących IXmlSerializable typów na serwerze proxy zamiast generować nowe. W tym przypadku można użyć funkcji typów, do których odwołuje się odwołanie opisane w temacie Importowanie schematu do generowania typów, aby wskazać typ do ponownego użycia. Odpowiada to użyciu przełącznika /reference svcutil.exe, który określa zestaw zawierający typy do ponownego użycia.

Zachowanie starszej wersji elementu XmlSerializer

W programie .NET Framework 4.0 i starszych program XmlSerializer wygenerował tymczasowe zestawy serializacji, pisząc kod języka C# do pliku. Plik został następnie skompilowany w zestawie. To zachowanie miało pewne niepożądane konsekwencje, takie jak spowolnienie czasu uruchamiania serializatora. W programie .NET Framework 4.5 to zachowanie zostało zmienione w celu wygenerowania zestawów bez konieczności używania kompilatora. Niektórzy deweloperzy mogą chcieć zobaczyć wygenerowany kod języka C#. Możesz określić, aby użyć tego starszego zachowania, korzystając z następującej konfiguracji:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.xml.serialization>
    <xmlSerializer tempFilesLocation='e:\temp\XmlSerializerBug' useLegacySerializerGeneration="true" />
  </system.xml.serialization>
  <system.diagnostics>
    <switches>
      <add name="XmlSerialization.Compilation" value="1" />
    </switches>
  </system.diagnostics>
</configuration>

Jeśli wystąpią problemy ze zgodnością, takie jak XmlSerializer niepowodzenie serializacji klasy pochodnej z nowym przesłonięciem innej niż publiczna, możesz wrócić do starszego XMLSerializer zachowania przy użyciu następującej konfiguracji:

<configuration>
  <appSettings>
    <add key="System:Xml:Serialization:UseLegacySerializerGeneration" value="true" />
  </appSettings>
</configuration>

Alternatywą dla powyższej konfiguracji jest użycie następującej konfiguracji na maszynie z programem .NET Framework 4.5 lub nowszym:

<configuration>
  <system.xml.serialization>
    <xmlSerializer useLegacySerializerGeneration="true"/>
  </system.xml.serialization>
</configuration>

Uwaga

Przełącznik <xmlSerializer useLegacySerializerGeneration="true"/> działa tylko na maszynie z programem .NET Framework 4.5 lub nowszym. Powyższe appSettings podejście działa we wszystkich wersjach programu .NET Framework.

Zobacz też