Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Windows Communication Foundation (WCF) kann zwei verschiedene Serialisierungstechnologien verwenden, um die Daten in Ihrer Anwendung in XML umzuwandeln, die zwischen Clients und Diensten übertragen werden: DataContractSerializer
und XmlSerializer
.
DataContractSerializer
Standardmäßig verwendet WCF die DataContractSerializer Klasse zum Serialisieren von Datentypen. Dieser Serialisierer unterstützt die folgenden Typen:
Grundtypen (z. B. Integer, Zeichenfolgen und Bytearrays) sowie einige spezielle Typen, wie XmlElement und DateTime, die als Grundtypen behandelt werden.
Datenvertragstypen (Typen, die mit dem DataContractAttribute Attribut gekennzeichnet sind).
Typen, die mit dem SerializableAttribute Attribut gekennzeichnet sind, einschließlich Typen, die die ISerializable Schnittstelle implementieren.
Typen, die die IXmlSerializable Schnittstelle implementieren.
Viele gängige Sammlungstypen, die viele generische Sammlungstypen enthalten.
Viele .NET Framework-Typen fallen in die letzten beiden Kategorien und sind somit serialisierbar. Arrays serialisierbarer Typen sind ebenfalls serialisierbar. Eine vollständige Liste finden Sie unter Angeben der Datenübertragung in Serviceverträgen.
Der DataContractSerializer, der zusammen mit Datenvertragstypen verwendet wird, ist die empfohlene Methode, um neue WCF-Dienste zu schreiben. Weitere Informationen finden Sie unter Verwenden von Datenverträgen.
XmlSerializer
WCF unterstützt auch die XmlSerializer Klasse. Die XmlSerializer Klasse ist nicht für WCF eindeutig. Es ist dasselbe Serialisierungsmodul, das ASP.NET Webdienste verwenden. Die XmlSerializer Klasse unterstützt einen viel engeren Satz von Typen als die DataContractSerializer Klasse, ermöglicht aber viel mehr Kontrolle über das resultierende XML und unterstützt viel mehr vom XSD-Standard (XML Schema Definition Language). Außerdem sind keine deklarativen Attribute für serialisierbare Typen erforderlich. Weitere Informationen finden Sie im Thema zur XML-Serialisierung in der .NET Framework-Dokumentation. Die XmlSerializer Klasse unterstützt keine Datenvertragstypen.
Wenn Sie Svcutil.exe oder das Feature " Dienstreferenz hinzufügen " in Visual Studio verwenden, um Clientcode für einen Drittanbieterdienst zu generieren oder auf ein Drittanbieterschema zuzugreifen, wird automatisch ein entsprechender Serialisierer für Sie ausgewählt. Wenn das Schema nicht mit dem DataContractSerializerSchema kompatibel ist, wird die XmlSerializer Option ausgewählt.
Wechseln zum XmlSerializer
Gelegentlich müssen Sie möglicherweise manuell auf XmlSerializer umschalten. Dies geschieht beispielsweise in den folgenden Fällen:
Wenn Sie eine Anwendung von ASP.NET Webdiensten zu WCF migrieren, sollten Sie vorhandene, XmlSerializerkompatible Typen wiederverwenden, anstatt neue Datentypen zu erstellen.
Wenn eine genaue Kontrolle über den XML-Code, der in Nachrichten angezeigt wird, wichtig ist, aber ein WSDL-Dokument (Web Services Description Language) nicht verfügbar ist, z. B. beim Erstellen eines Diensts mit Typen, die einem bestimmten standardisierten, veröffentlichten Schema entsprechen müssen, das nicht mit dem DataContractSerializer kompatibel ist.
Beim Erstellen von Diensten, die dem älteren SOAP-Codierungsstandard entsprechen.
In diesen und anderen Fällen können Sie manuell zur XmlSerializer Klasse wechseln, indem Sie das XmlSerializerFormatAttribute
Attribut auf Ihren Dienst anwenden, wie im folgenden Code gezeigt.
[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.
Sicherheitsüberlegungen
Hinweis
Es ist wichtig, beim Wechsel von Serialisierungs-Engines vorsichtig zu sein. Je nach verwendetem Serializer kann derselbe Typ unterschiedlich in XML serialisiert werden. Wenn Sie versehentlich den falschen Serialisierer verwenden, geben Sie möglicherweise Informationen aus dem Typ an, den Sie nicht offenlegen wollten.
Die DataContractSerializer Klasse serialisiert beispielsweise nur die Mitglieder, die mit dem DataMemberAttribute Attribut gekennzeichnet sind, wenn Datenvertrags-Typen serialisiert werden. Die XmlSerializer-Klasse serialisiert jeden öffentlichen Member. Sehen Sie sich den Typ im folgenden Code an.
[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
Wenn der Typ versehentlich in einem Dienstvertrag verwendet wird, in dem die XmlSerializer Klasse ausgewählt ist, wird das creditCardNumber
Element serialisiert, was wahrscheinlich nicht beabsichtigt ist.
Obwohl die DataContractSerializer Klasse der Standard ist, können Sie sie explizit für Ihren Dienst auswählen (obwohl dies nie erforderlich sein sollte), indem Sie das DataContractFormatAttribute Attribut auf den Dienstvertragstyp anwenden.
Der für den Dienst verwendete Serialisierer ist ein integraler Bestandteil des Vertrags und kann nicht geändert werden, indem er eine andere Bindung auswählt oder andere Konfigurationseinstellungen ändert.
Andere wichtige Sicherheitsaspekte gelten für die XmlSerializer Klasse. Zunächst wird dringend empfohlen, dass jede WCF-Anwendung, die die XmlSerializer Klasse verwendet, mit einem Schlüssel signiert ist, der vor der Offenlegung geschützt ist. Diese Empfehlung gilt sowohl, wenn ein manueller Wechsel zu XmlSerializer erfolgt, als auch, wenn ein automatischer Wechsel erfolgt (durch Svcutil.exe, Dienstverweis hinzufügen oder ein ähnliches Tool). Dies liegt daran, dass das XmlSerializer Serialisierungsmodul das Laden von vorgenerierten Serialisierungsassemblys unterstützt, solange sie mit demselben Schlüssel wie die Anwendung signiert sind. Eine nicht signierte Anwendung ist völlig ungeschützt vor der Möglichkeit, dass eine böswillige Assembly mit dem erwarteten Namen der vorgenerierten Serialisierungsassembly im Anwendungsordner oder im globalen Assemblycache abgelegt wird. Natürlich muss ein Angreifer zunächst Schreibzugriff auf einen dieser beiden Speicherorte erhalten, um diese Aktion zu versuchen.
Eine weitere Bedrohung, die immer vorhanden ist, wenn Sie XmlSerializer verwenden, besteht im Zusammenhang mit dem Schreibzugriff auf den temporären Systemordner. Die XmlSerializer Serialisierungs-Engine erstellt und verwendet temporäre Serialisierungsassemblies in diesem Ordner. Beachten Sie, dass jeder Prozess mit Schreibzugriff auf den temporären Ordner diese Serialisierungsassemblys mit bösartigem Code überschreiben kann.
Regeln für xmlSerializer-Unterstützung
Sie können Attribute, die XmlSerializer-kompatibel sind, nicht direkt auf Vertragsvorgangsparameter oder Rückgabewerte anwenden. Sie können jedoch auf eingegebene Nachrichten (Nachrichten-Vertragstextteile) angewendet werden, wie im folgenden Code dargestellt.
[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
Wenn diese Attribute auf eingegebene Nachrichtenelemente angewendet werden, überschreiben diese Attribute Eigenschaften, die mit den typierten Nachrichtenattributen in Konflikt geraten. Im folgenden Code setzt zum Beispiel ElementName
Name
außer Kraft.
[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
Das MessageHeaderArrayAttribute Attribut wird bei Verwendung des Attributs XmlSerializernicht unterstützt.
Hinweis
In diesem Fall löst die XmlSerializer folgende Ausnahme aus, die vor WCF veröffentlicht wird: "Ein Element, das auf der obersten Ebene eines Schemas deklariert ist, darf 1 nicht aufweisen maxOccurs
> . Stellen Sie ein Wrapperelement für "more" bereit, indem Sie entweder XmlArray
oder das Wrapped-Parameterformat verwenden oder XmlArrayItem
anstelle von XmlElementAttribute
verwenden.
Wenn Sie eine solche Ausnahme erhalten, untersuchen Sie, ob diese Situation zutrifft.
WCF unterstützt die Attribute SoapIncludeAttribute und XmlIncludeAttribute in Nachrichtenverträgen und Operationsverträgen nicht; verwenden Sie stattdessen das KnownTypeAttribute Attribut.
Typen, die die IXmlSerializable-Schnittstelle implementieren
Typen, die die IXmlSerializable
Schnittstelle implementieren, werden vollständig von der DataContractSerializer
unterstützt. Das XmlSchemaProviderAttribute Attribut sollte immer auf diese Typen angewendet werden, um das Schema zu steuern.
Warnung
Wenn Sie polymorphe Typen serialisieren, müssen Sie das XmlSchemaProviderAttribute-Tag auf den Typ anwenden, um sicherzustellen, dass der richtige Typ serialisiert wird.
Es gibt drei Arten von Typen, die implementieren IXmlSerializable
: Typen, die beliebige Inhalte darstellen, Typen, die ein einzelnes Element darstellen, und Legacytypen DataSet .
Inhaltstypen verwenden eine vom
XmlSchemaProviderAttribute
Attribut angegebene Schemaanbietermethode. Die Methode gibt nicht zurücknull
, und die IsAny Eigenschaft für das Attribut bleibt am Standardwert vonfalse
. Dies ist die am häufigsten verwendete Verwendung vonIXmlSerializable
Typen.Elementtypen werden verwendet, wenn ein
IXmlSerializable
Typ seinen eigenen Stammelementnamen steuern muss. Wenn Sie einen Typ als Elementtyp markieren möchten, legen Sie entweder die IsAny Eigenschaft für das XmlSchemaProviderAttribute Attribut auftrue
, oder Sie gebennull
von der Schemaanbietermethode zurück. Eine Schemaanbietermethode ist für Elementtypen optional – Sie könnennull
anstelle des Methodennamens inXmlSchemaProviderAttribute
angeben. WennIsAny
true
ist und eine Schemaanbietermethode angegeben ist, muss die Methodenull
zurückgeben.Legacy-Typen DataSet sind
IXmlSerializable
Typen, die nicht mit demXmlSchemaProviderAttribute
Attribut gekennzeichnet sind. Stattdessen basieren sie auf der Methode für die GetSchema Schemagenerierung. Dieses Muster wird für denDataSet
-Typ verwendet, und sein typisiertes Dataset leitet in früheren Versionen des .NET Frameworks eine Klasse ab, ist jedoch inzwischen obsolet und wird nur aus Gründen der Kompatibilität unterstützt. Verlassen Sie sich nicht auf dieses Muster, sondern wenden Sie immerXmlSchemaProviderAttribute
auf IhreIXmlSerializable
-Typen an.
IXmlSerialisierbare Inhaltstypen
Beim Serialisieren eines Datenmitglieds eines Typs, der IXmlSerializable
implementiert und als Inhaltstyp wie zuvor definiert wurde, schreibt der Serialisierer das Wrapperelement für das Datenmitglied und übergibt die Steuerung an die WriteXml-Methode. Die WriteXml Implementierung kann einen beliebigen XML-Code schreiben, der das Hinzufügen von Attributen zum Wrapperelement enthält. Nachdem WriteXml
abgeschlossen ist, schließt das Serialisierungsprogramm das Element.
Wenn Sie einen Datenmember eines Typs deserialisieren, der IXmlSerializable
implementiert und ein wie zuvor definierter Inhaltstyp ist, ordnet das Deserialisierungsprogramm den XML-Reader im Wrapperelement für den Datenmember an und übergibt die Steuerung an die ReadXml-Methode. Die Methode muss das gesamte Element einschließlich der Start- und Endtags lesen. Stellen Sie sicher, dass ihr ReadXml
Code den Fall behandelt, in dem das Element leer ist. Darüber hinaus sollte Ihre ReadXml
Implementierung nicht darauf angewiesen sein, dass das Wrapperelement auf eine bestimmte Weise benannt ist. Der Name wird vom Serialisierer ausgewählt, kann variieren.
Es ist gestattet, Inhaltstypen polymorph zuzuweisenIXmlSerializable
, z. B. an Datenmitglieder des Typs Object. Es ist auch zulässig, dass die Typinstanzen null sind. Schließlich ist es möglich, IXmlSerializable
-Typen mit aktivierter Objektdiagramm-Erhaltung und mit dem NetDataContractSerializer zu verwenden. Alle diese Features erfordern den WCF-Serialisierer, um bestimmte Attribute an das Wrapperelement anzufügen, darunter "nil" und "type" im XML-Schemainstanz-Namespace sowie "Id", "Ref", "Type" und "Assembly" in einem WCF-spezifischen Namespace.
Attribute, die ignoriert werden, wenn ReadXml implementiert wird
Bevor Sie die Steuerung an Ihren ReadXml
Code übergeben, überprüft der Deserializer das XML-Element, erkennt diese speziellen XML-Attribute und wirkt darauf. Wenn beispielsweise "nil" lautet true
, wird ein Nullwert deserialisiert und ReadXml
nicht aufgerufen. Wenn Polymorphismus erkannt wird, werden die Inhalte des Elements deserialisiert, als wäre es ein anderer Typ. Die ReadXml
-Implementierung des polymorph zugewiesenen Typs wird aufgerufen. In jedem Fall sollte eine ReadXml
Implementierung diese speziellen Attribute ignorieren, da sie vom Deserializer behandelt werden.
Schemaüberlegungen für IXmlSerializable-Inhaltstypen
Beim Exportieren des Schemas und eines IXmlSerializable
Inhaltstyps wird die Schemaanbietermethode aufgerufen. Ein XmlSchemaSet wird an die Schemaanbieter-Methode übergeben. Die Methode kann dem Schemasatz ein beliebiges gültiges Schema hinzufügen. Der Schemasatz enthält das Schema, das zum Zeitpunkt des Schemaexports bereits bekannt ist. Wenn die Schemaanbietermethode dem Schemasatz ein Element hinzufügen muss, muss ermittelt werden, ob ein XmlSchema Mit dem entsprechenden Namespace bereits im Satz vorhanden ist. Wenn dies der Fall ist, muss die Schemaanbietermethode das neue Element zum vorhandenen XmlSchema
hinzufügen. Andernfalls muss eine neue XmlSchema
Instanz erstellt werden. Dies ist wichtig, wenn Arrays von IXmlSerializable
Typen verwendet werden. Wenn Sie z. B. über einen IXmlSerializable
Typ verfügen, der als Typ "A" im Namespace "B" exportiert wird, ist es möglich, dass die Schemaanbietermethode nach dem Zeitpunkt, zu dem die Schemaanbietermethode aufgerufen wird, bereits das Schema für "B" enthält, um den "ArrayOfA"-Typ zu enthalten.
Zusätzlich zum Hinzufügen von Typen zu XmlSchemaSet muss die Schemaanbietermethode für Inhaltstypen einen Wert zurückgeben, der nicht null ist. Sie kann einen XmlQualifiedName Wert zurückgeben, der den Namen des Schematyps angibt, der für den angegebenen IXmlSerializable
Typ verwendet werden soll. Dieser qualifizierte Name dient auch als Datenvertragsname und Namespace für den Typ. Es ist zulässig, einen Typ zurückzugeben, der im Schemasatz nicht sofort vorhanden ist, wenn die Schemaanbietermethode zurückgegeben wird. Es wird jedoch vorausgesetzt, dass der Typ nach dem Export aller verwandten Typen (die Export-Methode wird für alle relevanten Typen von XsdDataContractExporter aufgerufen, und es wird auf die Schemas-Eigenschaft zugegriffen) im Schemasatz vorhanden ist. Das Zugreifen auf die Schemas
-Eigenschaft, bevor alle relevanten Export
-Aufrufe durchgeführt wurden, kann zu einer XmlSchemaException führen. Weitere Informationen zum Exportprozess finden Sie unter Exportieren von Schemas aus Klassen.
Die Schemaanbietermethode kann auch den zu verwendenden XmlSchemaType zurückgeben. Der Typ kann anonym sein oder auch nicht. Wenn es anonym ist, wird das Schema für den IXmlSerializable
Typ jedes Mal als anonymer Typ exportiert, wenn der IXmlSerializable
Typ als Datenmememm verwendet wird. Der IXmlSerializable
Typ verfügt weiterhin über einen Datenvertragsnamen und einen Namespace. (Dies wird wie in Den Datenvertragsnamen beschrieben festgelegt, mit der Ausnahme, dass das DataContractAttribute Attribut nicht zum Anpassen des Namens verwendet werden kann.) Wenn es nicht anonym ist, muss es sich um einen der Typen in der XmlSchemaSet
. Dies entspricht dem Zurückgeben von XmlQualifiedName
für den Typ.
Darüber hinaus wird eine globale Elementdeklaration für den Typ exportiert. Wenn das XmlRootAttribute-Attribut nicht auf den Typ angewendet wurde, hat das Element denselben Namen und denselben Namespace wie der Datenvertrag, und seine Eigenschaft "nullfähig" ist true
. Die einzige Ausnahme ist der Schemanamespace (http://www.w3.org/2001/XMLSchema
) – wenn sich der Datenvertrag des Typs in diesem Namespace befindet, befindet sich das entsprechende globale Element im leeren Namespace, da es verboten ist, dem Schemanamespace neue Elemente hinzuzufügen. Wenn der Typ das XmlRootAttribute
Attribut zugewiesen ist, wird die globale Elementdeklaration mithilfe der folgenden Eigenschaften exportiert: ElementName, Namespace und IsNullable. Die Standardwerte mit XmlRootAttribute
sind der Name des Datenvertrags, ein leerer Namespace und "nullfähig" ist true
.
Die gleichen regeln für die globale Elementdeklaration gelten für ältere Datasettypen. Beachten Sie, dass XmlRootAttribute
die globalen Elementdeklarationen, die über benutzerdefinierten Code hinzugefügt wurden, nicht überschreiben kann, die entweder unter Verwendung der Schemaanbietermethode XmlSchemaSet
oder über GetSchema
für ältere Datensatztypen hinzugefügt wurden.
IXmlSerializable-Elementtypen
Für IXmlSerializable
-Elementtypen ist entweder die IsAny
-Eigenschaft auf true
festgelegt, oder ihre Schemaanbietermethode gibt null
zurück.
Die Serialisierung und Deserialisierung eines Elementtyps ähnelt der Serialisierung und Deserialisierung eines Inhaltstyps. Es gibt jedoch einige wichtige Unterschiede:
Von der
WriteXml
-Implementierung wird erwartet, dass sie genau ein Element schreibt (das natürlich mehrere untergeordnete Elemente enthalten kann). Sie sollte keine Attribute außerhalb dieses einzelnen Elements, mehrerer gleichgeordneter Elemente oder gemischten Inhalts schreiben. Das Element ist möglicherweise leer.Die
ReadXml
Implementierung sollte das Wrapperelement nicht lesen. Es wird erwartet, dass sie das einzelne Element liest, das vonWriteXml
erzeugt wird.Beim regelmäßigen Serialisieren eines Elementtyps (z. B. als Datenmitglied in einem Datenvertrag) gibt der Serialisierer ein Wrapperelement aus, bevor er wie bei Inhaltstypen
WriteXml
aufruft. Bei der Serialisierung eines Elementtyps auf oberster Ebene gibt der Serializer normalerweise kein Wrapperelement um das Element aus, dasWriteXml
schreibt, es sei denn, ein Stammname und ein Namespace werden explizit angegeben, wenn der Serializer mit den KonstruktorenDataContractSerializer
oderNetDataContractSerializer
erstellt wird. Weitere Informationen finden Sie unter Serialisierung und Deserialisierung.Beim Serialisieren eines Elementtyps auf der obersten Ebene ohne Angabe des Stammnamens und des Namespaces zur Erstellungszeit tun WriteStartObject und WriteEndObject im Wesentlichen nichts, während WriteObjectContent
WriteXml
aufruft. In diesem Modus kann das zu serialisierende Objekt nichtnull
sein und kann nicht polymorph zugewiesen werden. Außerdem kann die Objektdiagramm-Erhaltung nicht aktiviert werden, und dasNetDataContractSerializer
kann nicht verwendet werden.Wenn Sie einen Elementtyp auf der obersten Ebene deserialisieren, ohne den Stammnamen und den Namespace zur Erstellungszeit anzugeben, gibt IsStartObject
true
zurück, wenn der Anfang eines Elements gefunden werden kann. ReadObject mit demverifyObjectName
-Parameter auftrue
gesetzt, verhält sich auf die gleiche Weise wieIsStartObject
, bevor das Objekt tatsächlich gelesen wird.ReadObject
übergibt anschließend die Steuerung an dieReadXml
-Methode.
Das für Elementtypen exportierte Schema ist identisch mit dem XmlElement
Typ, der in einem früheren Abschnitt beschrieben wird, mit der Ausnahme, dass die Schemaanbietermethode dem XmlSchemaSet Typ zusätzliches Schema hinzufügen kann, ähnlich wie bei Inhaltstypen. Die Verwendung des XmlRootAttribute
Attributs mit Elementtypen ist nicht zulässig, und globale Elementdeklarationen werden für diese Typen nie ausgegeben.
Unterschiede zum XmlSerializer
Die IXmlSerializable
Schnittstelle und die Attribute XmlSchemaProviderAttribute
und XmlRootAttribute
werden ebenfalls von XmlSerializer verstanden. Es gibt jedoch einige Unterschiede bei der Behandlung dieser Daten im Datenvertragsmodell. Die wichtigen Unterschiede sind in der folgenden Liste zusammengefasst:
Die Schemaanbietermethode muss im
XmlSerializer
öffentlich sein, um verwendet zu werden, muss jedoch im Datenvertragsmodell nicht öffentlich sein.Die Schemaanbietermethode wird aufgerufen, wenn für
IsAny
im Datenvertragsmodelltrue
gilt, jedoch nicht für denXmlSerializer
.Wenn das
XmlRootAttribute
Attribut nicht für Inhalts- oder Legacy-Datasettypen vorhanden ist, exportiert diesXmlSerializer
eine globale Elementdeklaration im leeren Namespace. Im Datenvertragsmodell ist der verwendete Namespace normalerweise der Datenvertragsnamespace, wie zuvor beschrieben.
Beachten Sie diese Unterschiede beim Erstellen von Typen, die mit beiden Serialisierungstechnologien verwendet werden.
Importieren eines IXmlSerializable-Schemas
Beim Importieren eines schemas, das aus IXmlSerializable
Typen generiert wird, gibt es einige Möglichkeiten:
Das generierte Schema kann ein gültiges Datenvertragsschema sein, wie in der Datenvertragsschemareferenz beschrieben. In diesem Fall kann das Schema wie gewohnt importiert werden, und reguläre Datavertragstypen werden generiert.
Das generierte Schema ist möglicherweise kein gültiges Datenvertragsschema. Ihre Schemaanbietermethode kann z. B. Schema generieren, das XML-Attribute umfasst, die im Datenvertragsmodell nicht unterstützt werden. In diesem Fall können Sie das Schema als
IXmlSerializable
Typen importieren. Dieser Importmodus ist nicht standardmäßig aktiviert, kann aber problemlos aktiviert werden – z. B. mit dem/importXmlTypes
Befehlszeilenwechsel zum Metadatenhilfsprogramm ServiceModel (Svcutil.exe). Dies wird im Importschema zum Generieren von Klassen ausführlich beschrieben. Beachten Sie, dass Sie direkt mit dem XML-Code für Ihre Typinstanzen arbeiten müssen. Sie können auch eine andere Serialisierungstechnologie verwenden, die eine breitere Palette von Schemas unterstützt . Weitere Informationen finden Sie im Thema zur Verwendung desXmlSerializer
Schemas.Möglicherweise möchten Sie Ihre vorhandenen
IXmlSerializable
Typen im Proxy wiederverwenden, anstatt neue zu generieren. In diesem Fall kann das im Thema "Importieren von Schema zum Generieren von Typen" beschriebene Feature für referenzierte Typen verwendet werden, um den Typ anzugeben, der wiederverwendet werden soll. Dies entspricht dem Verwenden des Schalters/reference
für „svcutil.exe“. Damit wird die Assembly angegeben, die die wiederzuverwendenden Typen enthält.
XmlSerializer-Legacyverhalten
In .NET Framework 4.0 und früher generierte der XmlSerializer temporäre Serialisierungsassemblys durch Schreiben von C#-Code in eine Datei. Die Datei wurde dann in eine Assembly kompiliert. Dieses Verhalten hatte einige unerwünschte Folgen, z. B. das Verlangsamen der Startzeit für den Serialisierer. In .NET Framework 4.5 wurde dieses Verhalten geändert, um die Assemblys zu generieren, ohne dass der Compiler verwendet werden muss. Einige Entwickler möchten möglicherweise den generierten C#-Code sehen. Sie können angeben, dass dieses Legacyverhalten durch die folgende Konfiguration verwendet werden soll:
<?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>
Wenn Kompatibilitätsprobleme auftreten, z. B. XmlSerializer
-Fehler beim Serialisieren einer abgeleiteten Klasse mit einer nicht öffentlichen neuen Überschreibung, können Sie mithilfe der folgenden Konfiguration zurück zum Legacyverhalten von XMLSerializer
wechseln:
<configuration>
<appSettings>
<add key="System:Xml:Serialization:UseLegacySerializerGeneration" value="true" />
</appSettings>
</configuration>
Als Alternative zur obigen Konfiguration können Sie die folgende Konfiguration auf einem Computer verwenden, auf dem .NET Framework 4.5 oder höher ausgeführt wird:
<configuration>
<system.xml.serialization>
<xmlSerializer useLegacySerializerGeneration="true"/>
</system.xml.serialization>
</configuration>
Hinweis
Der <xmlSerializer useLegacySerializerGeneration="true"/>
Switch funktioniert nur auf einem Computer mit .NET Framework 4.5 oder höher. Der obige appSettings
Ansatz funktioniert für alle .NET Framework-Versionen.