Serialisatie en deserialisatie
Windows Communication Foundation (WCF) bevat een nieuwe serialisatie-engine, de DataContractSerializer. De DataContractSerializer vertaalt tussen .NET Framework-objecten en XML in beide richtingen. In dit onderwerp wordt uitgelegd hoe de serializer werkt.
Bij het serialiseren van .NET Framework-objecten begrijpt de serialisatieprogramma een verscheidenheid aan serialisatieprogrammeermodellen, waaronder het nieuwe gegevenscontract model. Zie Typen die worden ondersteund door de serializer voor gegevenscontractenvoor een volledige lijst met ondersteunde typen. Zie Data Contracts gebruikenvoor een inleiding tot gegevenscontracten.
Bij het deserialiseren van XML gebruikt de serialisatiefunctie de klassen XmlReader en XmlWriter. Het biedt ook ondersteuning voor de XmlDictionaryReader- en XmlDictionaryWriter-klassen om in sommige gevallen geoptimaliseerde XML te produceren, zoals bij het gebruik van de binaire XML-indeling van WCF.
WCF bevat ook een aanvullende serialisatiefunctie, de NetDataContractSerializer. De NetDataContractSerializer:
- Is niet beveiligd. Zie de beveiligingshandleiding binaryFormatter voor meer informatie.
- Is vergelijkbaar met de BinaryFormatter en SoapFormatter serializers, omdat er ook .NET Framework-typenamen worden verzonden als onderdeel van de geserialiseerde gegevens.
- Wordt gebruikt wanneer dezelfde typen worden gedeeld op het serialiseren en het deserialiseren eindigt.
Zowel DataContractSerializer als NetDataContractSerializer afgeleid van een gemeenschappelijke basisklasse, XmlObjectSerializer.
Waarschuwing
De DataContractSerializer serialiseert tekenreeksen die besturingstekens bevatten met een hexadecimale waarde onder 20 als XML-entiteiten. Dit kan een probleem veroorzaken met een niet-WCF-client bij het verzenden van dergelijke gegevens naar een WCF-service.
Een DataContractSerializer-instantie maken
Het bouwen van een exemplaar van de DataContractSerializer is een belangrijke stap. Na de constructie kunt u geen van de instellingen wijzigen.
Het hoofdtype opgeven
Het hoofdtype is het type van welke exemplaren worden geserialiseerd of gedeserialiseerd. De DataContractSerializer heeft veel constructoroverbelastingen, maar minimaal moet een hoofdtype worden opgegeven met behulp van de parameter type
.
Een serialisatiefunctie die voor een bepaald hoofdtype is gemaakt, kan niet worden gebruikt om een ander type te serialiseren (of deserialiseren), tenzij het type is afgeleid van het hoofdtype. In het volgende voorbeeld ziet u twee klassen.
[DataContract]
public class Person
{
// Code not shown.
}
[DataContract]
public class PurchaseOrder
{
// Code not shown.
}
<DataContract()> _
Public Class Person
' Code not shown.
End Class
<DataContract()> _
Public Class PurchaseOrder
' Code not shown.
End Class
Met deze code wordt een exemplaar van de DataContractSerializer
gemaakt dat alleen kan worden gebruikt om exemplaren van de Person
-klasse te serialiseren of deserialiseren.
DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
// This can now be used to serialize/deserialize Person but not PurchaseOrder.
Dim dcs As New DataContractSerializer(GetType(Person))
' This can now be used to serialize/deserialize Person but not PurchaseOrder.
Bekende typen opgeven
Als polymorfisme betrokken is bij de typen die worden geserialiseerd die nog niet worden verwerkt met behulp van het kenmerk KnownTypeAttribute of een ander mechanisme, moet een lijst met mogelijke bekende typen worden doorgegeven aan de constructor van de serializer met behulp van de parameter knownTypes
. Voor meer informatie over bekende typen, zie Bekende typen gegevenscontract.
In het volgende voorbeeld ziet u een klasse, LibraryPatron
, die een verzameling van een specifiek type, de LibraryItem
bevat. De tweede klasse definieert het LibraryItem
type. De derde en vier klassen (Book
en Newspaper
) nemen over van de LibraryItem
-klasse.
[DataContract]
public class LibraryPatron
{
[DataMember]
public LibraryItem[] borrowedItems;
}
[DataContract]
public class LibraryItem
{
// Code not shown.
}
[DataContract]
public class Book : LibraryItem
{
// Code not shown.
}
[DataContract]
public class Newspaper : LibraryItem
{
// Code not shown.
}
<DataContract()> _
Public Class LibraryPatron
<DataMember()> _
Public borrowedItems() As LibraryItem
End Class
<DataContract()> _
Public Class LibraryItem
' Code not shown.
End Class
<DataContract()> _
Public Class Book
Inherits LibraryItem
' Code not shown.
End Class
<DataContract()> _
Public Class Newspaper
Inherits LibraryItem
' Code not shown.
End Class
Met de volgende code wordt een exemplaar van de serializer gemaakt met behulp van de parameter knownTypes
.
// Create a serializer for the inherited types using the knownType parameter.
Type[] knownTypes = new Type[] { typeof(Book), typeof(Newspaper) };
DataContractSerializer dcs =
new DataContractSerializer(typeof(LibraryPatron), knownTypes);
// All types are known after construction.
' Create a serializer for the inherited types using the knownType parameter.
Dim knownTypes() As Type = {GetType(Book), GetType(Newspaper)}
Dim dcs As New DataContractSerializer(GetType(LibraryPatron), knownTypes)
' All types are known after construction.
De standaardhoofdnaam en -naamruimte opgeven
Normaal gesproken worden, wanneer een object wordt geserialiseerd, de standaardnaam en naamruimte van het buitenste XML-element bepaald op basis van de naam en naamruimte van het gegevenscontract. De namen van alle binnenste elementen worden bepaald op basis van namen van gegevensleden en hun naamruimte is de naamruimte van het gegevenscontract. In het volgende voorbeeld worden Name
en Namespace
waarden ingesteld in de constructors van de DataContractAttribute- en DataMemberAttribute-klassen.
[DataContract(Name = "PersonContract", Namespace = "http://schemas.contoso.com")]
public class Person2
{
[DataMember(Name = "AddressMember")]
public Address theAddress;
}
[DataContract(Name = "AddressContract", Namespace = "http://schemas.contoso.com")]
public class Address
{
[DataMember(Name = "StreetMember")]
public string street;
}
<DataContract(Name:="PersonContract", [Namespace]:="http://schemas.contoso.com")> _
Public Class Person2
<DataMember(Name:="AddressMember")> _
Public theAddress As Address
End Class
<DataContract(Name:="AddressContract", [Namespace]:="http://schemas.contoso.com")> _
Public Class Address
<DataMember(Name:="StreetMember")> _
Public street As String
End Class
Het serialiseren van een exemplaar van de klasse Person
produceert XML die vergelijkbaar is met de volgende.
<PersonContract xmlns="http://schemas.contoso.com">
<AddressMember>
<StreetMember>123 Main Street</StreetMember>
</AddressMember>
</PersonContract>
U kunt echter de standaardnaam en naamruimte van het hoofdelement aanpassen door de waarden van de parameters rootName
en rootNamespace
door te geven aan de DataContractSerializer constructor. Houd er rekening mee dat de rootNamespace
geen invloed heeft op de naamruimte van de ingesloten elementen die overeenkomen met gegevensleden. Dit is alleen van invloed op de naamruimte van het buitenste element.
Deze waarden kunnen worden doorgegeven als tekenreeksen of exemplaren van de XmlDictionaryString-klasse om hun optimalisatie mogelijk te maken met behulp van de binaire XML-indeling.
Het quotum voor maximumobjecten instellen
Sommige DataContractSerializer
constructoroverbelastingen hebben een maxItemsInObjectGraph
parameter. Deze parameter bepaalt het maximum aantal objecten dat door de serialisatiefunctie wordt geserialiseerd of gedeserialiseerd in één ReadObject methodeaanroep. (De methode leest altijd één hoofdobject, maar dit object heeft mogelijk andere objecten in de gegevensleden. Deze objecten kunnen andere objecten hebben, enzovoort.) De standaardwaarde is 65536. Houd er rekening mee dat bij het serialiseren of deserialiseren van matrices elke matrixvermelding als een afzonderlijk object wordt geteld. Houd er ook rekening mee dat sommige objecten mogelijk een grote geheugenweergave hebben en dat dit quotum alleen mogelijk niet voldoende is om een Denial of Service-aanval te voorkomen. Zie Beveiligingsoverwegingen voor gegevensvoor meer informatie. Als u dit quotum boven de standaardwaarde wilt verhogen, is het belangrijk dat u dit zowel doet aan de verzendende (serialiseren) als ontvangende (deserialiseren) zijden, omdat dit van toepassing is op zowel bij het lezen als schrijven van gegevens.
Rondreizen
Een rondreis treedt op wanneer een object in één bewerking wordt gedeserialiseerd en opnieuw geserialiseerd. Het gaat dus van XML naar een objectinstantie en weer terug naar een XML-stroom.
Sommige DataContractSerializer
constructoroverbelastingen hebben een ignoreExtensionDataObject
parameter, die standaard is ingesteld op false
. In deze standaardmodus kunnen gegevens worden verzonden tijdens een retour vanaf een nieuwere versie van een gegevenscontract via een oudere versie en terug naar de nieuwere versie zonder verlies, zolang het gegevenscontract de IExtensibleDataObject interface implementeert. Stel dat versie 1 van het Person
gegevenscontract de Name
en PhoneNumber
gegevensleden bevat en dat versie 2 een Nickname
lid toevoegt. Als IExtensibleDataObject
is geïmplementeerd, worden de Nickname
gegevens opgeslagen bij het verzenden van gegevens van versie 2 naar versie 1 en vervolgens opnieuw verzonden wanneer de gegevens opnieuw worden geserialiseerd; daarom gaan er geen gegevens verloren tijdens de retour. Zie Forward-Compatible Data Contracts en Data Contract Versioningvoor meer informatie.
Beveiligings- en schemavaliditeitsproblemen met rondreizen
Rondreizen kunnen implicaties voor de beveiliging hebben. Het deserialiseren en opslaan van grote hoeveelheden overbodige gegevens kan bijvoorbeeld een beveiligingsrisico vormen. Er zijn mogelijk beveiligingsproblemen over het opnieuw verzenden van deze gegevens die niet kunnen worden geverifieerd, met name als er digitale handtekeningen betrokken zijn. In het vorige scenario kan het eindpunt van versie 1 bijvoorbeeld een Nickname
waarde ondertekenen die schadelijke gegevens bevat. Ten slotte kan er sprake zijn van problemen met de geldigheid van het schema: een eindpunt kan altijd gegevens verzenden die strikt voldoen aan het vermelde contract en geen extra waarden. In het vorige voorbeeld geeft het contract van versie 1 aan dat het alleen Name
en PhoneNumber
verzendt, en als schemavalidatie wordt gebruikt, zorgt het verzenden van de extra Nickname
waarde ervoor dat validatie mislukt.
Retourreizen in- en uitschakelen
Om round-trips uit te schakelen, moet u de IExtensibleDataObject-interface niet implementeren. Als u geen controle hebt over de typen, stelt u de parameter ignoreExtensionDataObject
in op true
om hetzelfde effect te bereiken.
Behoud van objectgrafiek
Normaal gesproken geeft de serializer niet om objectidentiteit, zoals in de volgende code.
[DataContract]
public class PurchaseOrder
{
[DataMember]
public Address billTo;
[DataMember]
public Address shipTo;
}
[DataContract]
public class Address
{
[DataMember]
public string street;
}
<DataContract()> _
Public Class PurchaseOrder
<DataMember()> _
Public billTo As Address
<DataMember()> _
Public shipTo As Address
End Class
<DataContract()> _
Public Class Address
<DataMember()> _
Public street As String
End Class
Met de volgende code wordt een inkooporder gemaakt.
// Construct a purchase order:
Address adr = new Address();
adr.street = "123 Main St.";
PurchaseOrder po = new PurchaseOrder();
po.billTo = adr;
po.shipTo = adr;
' Construct a purchase order:
Dim adr As New Address()
adr.street = "123 Main St."
Dim po As New PurchaseOrder()
po.billTo = adr
po.shipTo = adr
Merk op dat de velden billTo
en shipTo
zijn ingesteld op hetzelfde objectexemplaar. De gegenereerde XML dupliceert echter de informatie en ziet er ongeveer zo uit als de volgende XML.
<PurchaseOrder>
<billTo><street>123 Main St.</street></billTo>
<shipTo><street>123 Main St.</street></shipTo>
</PurchaseOrder>
Deze aanpak heeft echter de volgende kenmerken, die mogelijk ongewenst zijn:
Voorstelling. Het repliceren van gegevens is inefficiënt.
Kringverwijzingen. Als objecten naar zichzelf verwijzen, zelfs via andere objecten, leidt serialiseren door replicatie tot een oneindige lus. (De serializer genereert een SerializationException als dit gebeurt.)
Semantiek. Soms is het belangrijk om het feit te behouden dat twee verwijzingen naar hetzelfde object zijn en niet naar twee identieke objecten.
Om deze redenen hebben sommige DataContractSerializer
constructoroverbelastingen een preserveObjectReferences
parameter (de standaardwaarde is false
). Wanneer deze parameter is ingesteld op true
, wordt een speciale methode voor het coderen van objectverwijzingen, die alleen door WCF wordt begrepen, gebruikt. Wanneer deze is ingesteld op true
, lijkt het XML-codevoorbeeld nu op het volgende.
<PurchaseOrder ser:id="1">
<billTo ser:id="2"><street ser:id="3">123 Main St.</street></billTo>
<shipTo ser:ref="2"/>
</PurchaseOrder>
De 'ser'-naamruimte verwijst naar de standaardserialisatienaamruimte, http://schemas.microsoft.com/2003/10/Serialization/
. Elk stukje gegevens wordt slechts één keer geserialiseerd en krijgt een id-nummer en daaropvolgende toepassingen resulteren in een verwijzing naar de reeds geserialiseerde gegevens.
Belangrijk
Als zowel de attributen 'id' en 'ref' aanwezig zijn in het gegevenscontract XMLElement
, wordt het attribuut 'ref' gehonoreerd en wordt het attribuut 'id' genegeerd.
Het is belangrijk om inzicht te hebben in de beperkingen van deze modus:
De XML die de
DataContractSerializer
produceert metpreserveObjectReferences
ingesteld optrue
is niet compatibel met andere technologieën en kan alleen worden geopend door een andereDataContractSerializer
instantie, ook metpreserveObjectReferences
ingesteld optrue
.Er is geen ondersteuning voor metagegevens (schema) voor deze functie. Het gegenereerde schema is alleen geldig voor het geval wanneer
preserveObjectReferences
is ingesteld opfalse
.Deze functie kan ertoe leiden dat het serialisatie- en deserialisatieproces langzamer wordt uitgevoerd. Hoewel gegevens niet hoeven te worden gerepliceerd, moeten extra objectvergelijkingen worden uitgevoerd in deze modus.
Waarschuwing
Wanneer de preserveObjectReferences
modus is ingeschakeld, is het vooral belangrijk om de maxItemsInObjectGraph
waarde in te stellen op het juiste quotum. Vanwege de manier waarop matrices in deze modus worden verwerkt, is het voor een aanvaller eenvoudig om een klein schadelijk bericht te maken dat resulteert in een groot geheugenverbruik dat alleen wordt beperkt door het maxItemsInObjectGraph
quotum.
Een surrogaat voor een gegevenscontract opgeven
Sommige DataContractSerializer
constructor-overbelastingen hebben een dataContractSurrogate
parameter, die kan worden ingesteld op null
. Anders kunt u deze gebruiken om een gegevenscontract surrogaatop te geven. Dit is een type waarmee de IDataContractSurrogate-interface wordt geïmplementeerd. Vervolgens kunt u de interface gebruiken om het serialisatie- en deserialisatieproces aan te passen. Zie Data Contract Surrogatesvoor meer informatie.
Serialisatie
De volgende informatie is van toepassing op alle klassen die overnemen van de XmlObjectSerializer, met inbegrip van de DataContractSerializer- en NetDataContractSerializer-klassen.
Eenvoudige serialisatie
De eenvoudigste manier om een object te serialiseren, is door het door te geven aan de WriteObject methode. Er zijn drie overloads, elk voor het schrijven naar een Stream, een XmlWriterof een XmlDictionaryWriter. Met de Stream overbelasting is de uitvoer XML-gecodeerd in UTF-8. Met de XmlDictionaryWriter overbelasting optimaliseert de serialisatiefunctie de uitvoer voor binaire XML.
Wanneer u de methode WriteObject gebruikt, gebruikt de serializer de standaardnaam en naamruimte voor het wrapper-element en schrijft deze samen met de inhoud (zie de vorige sectie 'De standaardhoofdnaam en naamruimte opgeven').
In het volgende voorbeeld ziet u hoe u met een XmlDictionaryWriterschrijft.
Person p = new Person();
DataContractSerializer dcs =
new DataContractSerializer(typeof(Person));
XmlDictionaryWriter xdw =
XmlDictionaryWriter.CreateTextWriter(someStream,Encoding.UTF8 );
dcs.WriteObject(xdw, p);
Dim p As New Person()
Dim dcs As New DataContractSerializer(GetType(Person))
Dim xdw As XmlDictionaryWriter = _
XmlDictionaryWriter.CreateTextWriter(someStream, Encoding.UTF8)
dcs.WriteObject(xdw, p)
Dit produceert XML die vergelijkbaar is met de volgende.
<Person>
<Name>Jay Hamlin</Name>
<Address>123 Main St.</Address>
</Person>
Stap-By-Step serialisatie
Gebruik de methoden WriteStartObject, WriteObjectContenten WriteEndObject om het eindelement te schrijven, de inhoud van het object te schrijven en het wrapper-element respectievelijk te sluiten.
Notitie
Er zijn geen Stream overbelastingen van deze methoden.
Deze stapsgewijze serialisatie heeft twee veelvoorkomende toepassingen. Een is het invoegen van inhoud, zoals kenmerken of opmerkingen tussen WriteStartObject
en WriteObjectContent
, zoals wordt weergegeven in het volgende voorbeeld.
dcs.WriteStartObject(xdw, p);
xdw.WriteAttributeString("serializedBy", "myCode");
dcs.WriteObjectContent(xdw, p);
dcs.WriteEndObject(xdw);
dcs.WriteStartObject(xdw, p)
xdw.WriteAttributeString("serializedBy", "myCode")
dcs.WriteObjectContent(xdw, p)
dcs.WriteEndObject(xdw)
Dit produceert XML die vergelijkbaar is met de volgende.
<Person serializedBy="myCode">
<Name>Jay Hamlin</Name>
<Address>123 Main St.</Address>
</Person>
Een ander veelvoorkomend gebruik is om het gebruik van WriteStartObject en WriteEndObject volledig te vermijden, en om uw eigen aangepaste wrapper-element te schrijven (of zelfs het schrijven van een wrapper over te slaan), zoals wordt weergegeven in de volgende code.
xdw.WriteStartElement("MyCustomWrapper");
dcs.WriteObjectContent(xdw, p);
xdw.WriteEndElement();
xdw.WriteStartElement("MyCustomWrapper")
dcs.WriteObjectContent(xdw, p)
xdw.WriteEndElement()
Dit produceert XML die vergelijkbaar is met de volgende.
<MyCustomWrapper>
<Name>Jay Hamlin</Name>
<Address>123 Main St.</Address>
</MyCustomWrapper>
Notitie
Als u stapsgewijze serialisatie gebruikt, kan dit leiden tot schema-ongeldige XML.
Deserialisatie
De volgende informatie is van toepassing op alle klassen die overnemen van de XmlObjectSerializer, met inbegrip van de DataContractSerializer- en NetDataContractSerializer-klassen.
De meest eenvoudige manier om een object te deserialiseren is door een van de ReadObject methode-overbelastingen aan te roepen. Er zijn drie overloads, één voor het lezen met een XmlDictionaryReader, één met een XmlReader
, of één met een Stream
. Houd er rekening mee dat de Stream
overbelasting een tekstuele XmlDictionaryReader maakt die niet wordt beveiligd door quota en alleen moet worden gebruikt voor het lezen van vertrouwde gegevens.
Houd er ook rekening mee dat het object dat de ReadObject
methode retourneert, naar het juiste type moet worden gecast.
Met de volgende code wordt een exemplaar van de DataContractSerializer en een XmlDictionaryReadergemaakt en vervolgens een Person
exemplaar gedeserialiseerd.
DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
FileStream fs = new FileStream(path, FileMode.Open);
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
Person p = (Person)dcs.ReadObject(reader);
Dim dcs As New DataContractSerializer(GetType(Person))
Dim fs As New FileStream(path, FileMode.Open)
Dim reader As XmlDictionaryReader = _
XmlDictionaryReader.CreateTextReader(fs, New XmlDictionaryReaderQuotas())
Dim p As Person = CType(dcs.ReadObject(reader), Person)
Voordat u de methode ReadObject aanroept, plaatst u de XML-lezer op het wrapper-element of op een niet-inhoudsknooppunt dat voorafgaat aan het wrapper-element. U kunt dit doen door de Read methode van de XmlReader of de afleiding aan te roepen en de NodeTypete testen, zoals wordt weergegeven in de volgende code.
DataContractSerializer ser = new DataContractSerializer(typeof(Person),
"Customer", @"http://www.contoso.com");
FileStream fs = new FileStream(path, FileMode.Open);
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (ser.IsStartObject(reader))
{
Console.WriteLine("Found the element");
Person p = (Person)ser.ReadObject(reader);
Console.WriteLine($"{p.Name} {p.Address} id:{2}");
}
Console.WriteLine(reader.Name);
break;
}
}
Dim ser As New DataContractSerializer(GetType(Person), "Customer", "http://www.contoso.com")
Dim fs As New FileStream(path, FileMode.Open)
Dim reader As XmlDictionaryReader = XmlDictionaryReader.CreateTextReader(fs, New XmlDictionaryReaderQuotas())
While reader.Read()
Select Case reader.NodeType
Case XmlNodeType.Element
If ser.IsStartObject(reader) Then
Console.WriteLine("Found the element")
Dim p As Person = CType(ser.ReadObject(reader), Person)
Console.WriteLine("{0} {1}", _
p.Name, p.Address)
End If
Console.WriteLine(reader.Name)
End Select
End While
Houd er rekening mee dat u kenmerken van dit wrapper-element kunt lezen voordat u de lezer aan ReadObject
overhandigt.
Wanneer u een van de eenvoudige ReadObject
overbelastingen gebruikt, zoekt de deserializer naar de standaardnaam en naamruimte op het wrapper-element (zie de vorige sectie, 'De standaardhoofdnaam en naamruimte opgeven') en genereert een uitzondering als er een onbekend element wordt gevonden. In het voorgaande voorbeeld wordt het element <Person>
wrapper verwacht. De methode IsStartObject wordt aangeroepen om te controleren of de lezer gepositioneerd is op een element dat zoals verwacht is genoemd.
Er is een manier om deze wrapper-elementnaamcontrole uit te schakelen; sommige overbelastingen van de methode ReadObject
nemen de Booleaanse parameter verifyObjectName
, die standaard is ingesteld op true
. Als deze is ingesteld op false
, worden de naam en naamruimte van het wrapper-element genegeerd. Dit is handig voor het lezen van XML die is geschreven met behulp van het stapsgewijze serialisatiemechanisme dat eerder is beschreven.
NetDataContractSerializer gebruiken
Het belangrijkste verschil tussen de DataContractSerializer
en de NetDataContractSerializer is dat de DataContractSerializer
gegevenscontractnamen gebruikt, terwijl de NetDataContractSerializer
volledige .NET Framework-assembly uitvoert en namen typt in de geserialiseerde XML. Dit betekent dat dezelfde typen moeten worden gedeeld tussen de serialisatie- en deserialisatie-eindpunten. Dit betekent dat het mechanisme voor bekende typen niet vereist is bij de NetDataContractSerializer
omdat de exacte typen die moeten worden gedeserialiseerd altijd bekend zijn.
Er kunnen echter verschillende problemen optreden:
Beveiliging. Elk type dat wordt gevonden in de XML die wordt gedeserialiseerd, wordt geladen. Dit kan mogelijk worden misbruikt om het laden van kwaadaardige typen te forceren. Het gebruik van de
NetDataContractSerializer
met niet-vertrouwde gegevens moet alleen worden uitgevoerd als een serialisatiebinder wordt gebruikt (met behulp van de eigenschap Binder of constructorparameter). Met de binder kunnen alleen veilige typen worden geladen. Het Binder-mechanisme is identiek aan het mechanisme dat wordt gebruikt in de System.Runtime.Serialization naamruimte.Versiebeheer. Als u volledige type- en assemblynamen in de XML gebruikt, wordt de manier waarop typen kunnen worden geversioneerd ernstig beperkt. Het volgende kan niet worden gewijzigd: typ namen, naamruimten, assemblynamen en assemblyversies. Als u de AssemblyFormat eigenschap of constructorparameter instelt op Simple in plaats van de standaardwaarde van Full kunnen wijzigingen in de assemblyversie worden aangebracht, maar niet voor algemene parametertypen.
Interoperabiliteit. Omdat .NET Framework-typen en assemblynamen zijn opgenomen in de XML, hebben andere platforms dan .NET Framework geen toegang tot de resulterende gegevens.
Voorstelling. Door het type en de assemblynamen te schrijven, neemt de grootte van de resulterende XML aanzienlijk toe.
Dit mechanisme is vergelijkbaar met binaire of SOAP-serialisatie die wordt gebruikt door externe communicatie van .NET Framework (met name de BinaryFormatter en de SoapFormatter).
Het gebruik van de NetDataContractSerializer
is vergelijkbaar met het gebruik van de DataContractSerializer
, met de volgende verschillen:
Voor de constructors hoeft u geen basistype op te geven. U kunt elk type serialiseren met hetzelfde exemplaar van de
NetDataContractSerializer
.De constructors accepteren geen lijst met bekende typen. Het mechanisme voor bekende typen is niet nodig als typenamen in de XML worden geserialiseerd.
De constructors accepteren geen surrogaat voor een gegevenscontract. In plaats daarvan accepteren ze een ISurrogateSelector parameter met de naam
surrogateSelector
(die wordt toegewezen aan de eigenschap SurrogateSelector). Dit is een verouderd surrogaatmechanisme.De constructors accepteren een parameter met de naam
assemblyFormat
van de FormatterAssemblyStyle die is toegewezen aan de eigenschap AssemblyFormat. Zoals eerder besproken, kan dit worden gebruikt om de versiebeheermogelijkheden van de serializer te verbeteren. Dit is identiek aan het FormatterAssemblyStyle mechanisme in binaire of SOAP-serialisatie.De constructors accepteren een StreamingContext parameter met de naam
context
die is toegewezen aan de eigenschap Context. U kunt dit gebruiken om informatie door te geven aan typen die worden geserialiseerd. Dit gebruik is identiek aan dat van het StreamingContext mechanisme dat wordt gebruikt in andere System.Runtime.Serialization klassen.De methoden Serialize en Deserialize zijn aliassen voor de methoden WriteObject en ReadObject. Deze bestaan om een consistenter programmeermodel te bieden met binaire of SOAP-serialisatie.
Zie Binaire serialisatievoor meer informatie over deze functies.
De XML-indelingen die de NetDataContractSerializer
en het DataContractSerializer
gebruiken zijn normaal gesproken niet compatibel. Dat wil zeggen dat proberen te serialiseren met een van deze serializers en te deserialiseren met de andere geen ondersteund scenario is.
Houd er ook rekening mee dat de NetDataContractSerializer
niet de volledige .NET Framework-type en assemblynaam uitvoert voor elk knooppunt in de objectgrafiek. Deze uitvoer levert alleen informatie op waar deze niet eenduidig is. Dat wil zeggen, het genereert op het niveau van het hoofdobject en voor alle polymorfe gevallen.