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 Name
wartość .
[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 zwracanull
wartości , a IsAny właściwość atrybutu jest pozostawiona na wartości domyślnejfalse
. Jest to najbardziej typowe użycieIXmlSerializable
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 natrue
wartość lub powrótnull
z metody dostawcy schematu. Posiadanie metody dostawcy schematu jest opcjonalne dla typów elementów — można określićnull
zamiast nazwy metody w plikuXmlSchemaProviderAttribute
. JeśliIsAny
jednak określonotrue
metodę dostawcy schematu, metoda musi zwrócićnull
wartość .Starsze DataSet typy to
IXmlSerializable
typy, które nie są oznaczone atrybutemXmlSchemaProviderAttribute
. Zamiast tego polegają na metodzie generowania GetSchema schematu. Ten wzorzec jest używany dlaDataSet
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ówIXmlSerializable
.
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 XmlSchema
elementu . 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ę null
dostawcy 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óryWriteXml
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
WriteXml
elementu , 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óryWriteXml
zapisuje, chyba że główna nazwa i przestrzeń nazw są jawnie określone podczas konstruowania serializatora wDataContractSerializer
konstruktorach lubNetDataContractSerializer
. 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żnanull
przypisać obiektu serializowanego i nie można go przypisać polimorficznie. Ponadto nie można włączyć zachowywania grafu obiektów iNetDataContractSerializer
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 ustawionymverifyObjectName
natrue
zachowanie w taki sam sposób jakIsStartObject
przed faktycznym odczytaniem obiektu.ReadObject
następnie przekazuje kontrolę doReadXml
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 elementuXmlSerializer
.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 programuXmlSerializer
.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.