Condividi tramite


Serializzazione e deserializzazione

Windows Communication Foundation (WCF) include un nuovo motore di serializzazione, ovvero DataContractSerializer. DataContractSerializer traduce tra oggetti .NET Framework e XML, in entrambe le direzioni. In questo argomento viene illustrato il funzionamento del serializzatore.

Quando si serializzano oggetti .NET Framework, il serializzatore comprende un'ampia gamma di modelli di programmazione di serializzazione, incluso il nuovo modello di contratto dati . Per un elenco completo dei tipi supportati, vedere Tipi supportati dal serializzatore di contratti dati. Per un'introduzione ai contratti dati, vedere Uso dei contratti dati.

Durante la deserializzazione di XML, il serializzatore utilizza le XmlReader classi e XmlWriter . Supporta inoltre le XmlDictionaryReader classi e XmlDictionaryWriter per abilitarla per produrre codice XML ottimizzato in alcuni casi, ad esempio quando si usa il formato XML binario WCF.

WCF include anche un serializzatore complementare, ovvero NetDataContractSerializer. NetDataContractSerializer:

  • Non è sicuro. Per altre informazioni, vedere la guida alla sicurezza BinaryFormatter.
  • È simile ai serializzatori BinaryFormatter e SoapFormatter perché emette anch'esso i nomi dei tipi del .NET Framework come parte dei dati serializzati.
  • Viene utilizzato quando gli stessi tipi sono condivisi sia in fase di serializzazione che di deserializzazione.

Sia DataContractSerializer che NetDataContractSerializer derivano da una classe base comune, XmlObjectSerializer.

Avvertimento

DataContractSerializer Serializza stringhe contenenti caratteri di controllo con un valore esadecimale inferiore a 20 come entità XML. Ciò può causare un problema con un client non WCF quando si inviano tali dati a un servizio WCF.

Creazione di un'istanza di DataContractSerializer

La creazione di un'istanza di DataContractSerializer è un passaggio importante. Dopo la costruzione, non è possibile modificare alcuna delle impostazioni.

Specificazione del tipo radice

Il tipo radice è il tipo di istanze serializzate o deserializzate. Il DataContractSerializer ha molti overload del costruttore, ma, almeno, un tipo radice deve essere fornito usando il parametro type.

Un serializzatore creato per un determinato tipo radice non può essere utilizzato per serializzare (o deserializzare) un altro tipo, a meno che il tipo non sia derivato dal tipo radice. Nell'esempio seguente vengono illustrate due classi.

[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

Questo codice costruisce un'istanza DataContractSerializer di che può essere utilizzata solo per serializzare o deserializzare istanze della Person classe .

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.

Specifica di tipi noti

Se il polimorfismo è coinvolto nei tipi serializzati che non sono già gestiti utilizzando l'attributo KnownTypeAttribute o un altro meccanismo, è necessario passare un elenco di possibili tipi noti al costruttore del serializzatore usando il knownTypes parametro . Per altre informazioni sui tipi noti, vedere Tipi noti del contratto dati.

Nell'esempio seguente viene illustrata una classe , LibraryPatron, che include una raccolta di un tipo specifico, ovvero LibraryItem. La seconda classe definisce il LibraryItem tipo. La terza e quattro classi (Book e Newspaper) ereditano dalla LibraryItem classe .

[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

Il codice seguente costruisce un'istanza del serializzatore usando il knownTypes parametro .

// 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.

Specificare il nome radice predefinito e lo spazio dei nomi

In genere, quando un oggetto viene serializzato, il nome predefinito e lo spazio dei nomi dell'elemento XML più esterno vengono determinati in base al nome e allo spazio dei nomi del contratto dati. I nomi di tutti gli elementi interni vengono determinati dai nomi dei membri dei dati e il loro spazio dei nomi è lo spazio dei nomi di contratto di dati. Nell'esempio seguente, i valori Name e Namespace vengono impostati nei costruttori delle classi DataContractAttribute e DataMemberAttribute.

[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

La serializzazione di un'istanza della Person classe produce codice XML simile al seguente.

<PersonContract xmlns="http://schemas.contoso.com">  
  <AddressMember>  
    <StreetMember>123 Main Street</StreetMember>  
   </AddressMember>  
</PersonContract>  

Tuttavia, è possibile personalizzare il nome predefinito e lo spazio dei nomi dell'elemento radice passando i valori dei rootName parametri e rootNamespace al DataContractSerializer costruttore. Si noti che rootNamespace non influisce sullo spazio dei nomi degli elementi contenuti che corrispondono ai membri dati. Influisce solo sullo spazio dei nomi dell'elemento più esterno.

Questi valori possono essere passati come stringhe o istanze della XmlDictionaryString classe per consentire l'ottimizzazione usando il formato XML binario.

Impostazione della quota massima di oggetti

Alcuni sovraccarichi DataContractSerializer del costruttore hanno un parametro maxItemsInObjectGraph. Questo parametro determina il numero massimo di oggetti che il serializzatore serializza o deserializza in una singola ReadObject chiamata al metodo. Il metodo legge sempre un oggetto radice, ma questo oggetto può avere altri oggetti nei relativi membri dati. Tali oggetti possono avere altri oggetti e così via. Il valore predefinito è 65536. Si noti che durante la serializzazione o la deserializzazione di matrici, ogni voce di matrice viene conteggiato come oggetto separato. Si noti inoltre che alcuni oggetti possono avere una rappresentazione di memoria di grandi dimensioni e pertanto questa quota da sola potrebbe non essere sufficiente per impedire un attacco Denial of Service. Per altre informazioni, vedere Considerazioni sulla sicurezza per i dati. Se è necessario aumentare questa quota oltre il valore predefinito, è importante farlo sia sul lato invio (serializzazione) che sulla ricezione (deserializzazione) perché si applica sia alla lettura che alla scrittura dei dati.

Viaggi di andata e ritorno

Un round trip si verifica quando un oggetto viene deserializzato e serializzato nuovamente in un'unica operazione. Di conseguenza, passa da XML a un'istanza di oggetto e torna in un flusso XML.

Alcuni DataContractSerializer sovraccarichi del costruttore hanno un parametro ignoreExtensionDataObject, che è impostato su false per impostazione predefinita. In questa modalità predefinita, i dati possono essere inviati in un round trip da una versione più recente di un contratto dati tramite una versione precedente e tornare alla versione più recente senza perdita, purché il contratto dati implementi l'interfaccia IExtensibleDataObject . Si supponga, ad esempio, che la versione 1 del contratto dati Person contenga i membri dati Name e PhoneNumber, e che la versione 2 Name aggiunga un membro . Se IExtensibleDataObject viene implementato, quando si inviano informazioni dalla versione 2 alla versione 1, i Nickname dati vengono archiviati e quindi nuovamente generati quando i dati vengono serializzati nuovamente, pertanto non vengono persi dati nel round trip. Per altre informazioni, vedere Forward-Compatible Contratti di Dati e Versioning del Contratto Dati.

Problemi di sicurezza e validità dello schema con round trip

I round trip possono avere implicazioni per la sicurezza. Ad esempio, la deserializzazione e l'archiviazione di grandi quantità di dati estranei possono essere un rischio per la sicurezza. Potrebbero esserci problemi di sicurezza relativi alla ricreazione di questi dati che non è possibile verificare, soprattutto se sono coinvolte firme digitali. Ad esempio, nello scenario precedente, l'endpoint della versione 1 potrebbe firmare un Nickname valore che contiene dati dannosi. Infine, potrebbero esserci problemi di validità dello schema: un endpoint può voler sempre generare dati che rispettano rigorosamente il contratto dichiarato e non alcun valore aggiuntivo. Nell'esempio precedente il contratto dell'endpoint versione 1 indica che genera solo Name e PhoneNumbere se viene usata la convalida dello schema, l'emissione del valore aggiuntivo Nickname causa l'esito negativo della convalida.

Abilitazione e disabilitazione dei viaggi di andata e ritorno

Per disattivare il round trip, non implementare l'interfaccia IExtensibleDataObject. Se non si ha alcun controllo sui tipi, impostare il ignoreExtensionDataObject parametro su true per ottenere lo stesso effetto.

Conservazione dell'oggetto grafico

In genere, il serializzatore non si preoccupa dell'identità dell'oggetto, come nel codice seguente.

[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

Il codice seguente crea un ordine di acquisto.

// 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

Si noti che i campi billTo e shipTo vengono impostati sulla stessa istanza dell'oggetto. Tuttavia, il codice XML generato duplica le informazioni duplicate e ha un aspetto simile al codice XML seguente.

<PurchaseOrder>  
  <billTo><street>123 Main St.</street></billTo>  
  <shipTo><street>123 Main St.</street></shipTo>  
</PurchaseOrder>  

Tuttavia, questo approccio presenta le caratteristiche seguenti, che possono essere indesiderate:

  • Prestazione. La replica dei dati non è efficiente.

  • Riferimenti circolari. Se gli oggetti si riferiscono a se stessi, anche tramite altri oggetti, la serializzazione in base alla replica comporta un ciclo infinito. Il serializzatore genera un'eccezione SerializationException in questo caso.

  • Semantica. A volte è importante mantenere il fatto che due riferimenti siano allo stesso oggetto e non a due oggetti identici.

Per questi motivi, alcuni sovraccarichi del costruttore hanno un parametro DataContractSerializer (dove il valore predefinito è preserveObjectReferences). Quando questo parametro è impostato su true, viene usato un metodo speciale di riferimento all'oggetto di codifica, che riconosce solo WCF. Se impostato su true, l'esempio di codice XML è ora simile al seguente.

<PurchaseOrder ser:id="1">  
  <billTo ser:id="2"><street ser:id="3">123 Main St.</street></billTo>  
  <shipTo ser:ref="2"/>  
</PurchaseOrder>  

Lo spazio dei nomi "ser" fa riferimento allo spazio dei nomi di serializzazione standard, http://schemas.microsoft.com/2003/10/Serialization/. Ogni parte di dati viene serializzata una sola volta e viene assegnato un numero ID e gli usi successivi generano un riferimento ai dati già serializzati.

Importante

Se entrambi gli attributi "id" e "ref" sono presenti nel contratto XMLElementdati , l'attributo "ref" viene rispettato e l'attributo "id" viene ignorato.

È importante comprendere le limitazioni di questa modalità:

  • Il codice XML prodotto DataContractSerializer con preserveObjectReferences impostato su true non è interoperabile con altre tecnologie e può essere accessibile solo da un'altra DataContractSerializer istanza, anche con preserveObjectReferences impostato su true.

  • Non è disponibile alcun supporto di metadati (schema) per questa funzionalità. Lo schema prodotto è valido solo per il caso in cui preserveObjectReferences è impostato su false.

  • Questa funzionalità può causare un rallentamento del processo di serializzazione e deserializzazione. Anche se i dati non devono essere replicati, è necessario eseguire confronti di oggetti aggiuntivi in questa modalità.

Attenzione

Quando la preserveObjectReferences modalità è abilitata, è particolarmente importante impostare il maxItemsInObjectGraph valore sulla quota corretta. A causa del modo in cui le matrici vengono gestite in questa modalità, è facile per un utente malintenzionato creare un piccolo messaggio dannoso che comporta un consumo elevato di memoria limitato solo dalla maxItemsInObjectGraph quota.

Specificazione di un surrogato di contratto di dati

Alcuni DataContractSerializer sovraccarichi del costruttore hanno un dataContractSurrogate parametro, che può essere impostato su null. In caso contrario, è possibile usarlo per specificare un surrogato del contratto dati, ovvero un tipo che implementa l'interfaccia IDataContractSurrogate . È quindi possibile usare l'interfaccia per personalizzare il processo di serializzazione e deserializzazione. Per altre informazioni, vedere Sostituti del contratto di dati.

Serializzazione

Le informazioni seguenti si applicano a qualsiasi classe che eredita da XmlObjectSerializer, incluse le DataContractSerializer classi e NetDataContractSerializer .

Serializzazione semplice

Il modo più semplice per serializzare un oggetto consiste nel passarlo al WriteObject metodo . Sono disponibili tre overload, uno per la scrittura in un Stream oggetto, un XmlWriter oggetto o un XmlDictionaryWriter oggetto. Con il sovraccarico, l'output è Stream XML nella codifica UTF-8. Con l'overload XmlDictionaryWriter, il serializzatore ottimizza il suo output per il formato XML binario.

Quando si utilizza il metodo WriteObject, il serializzatore usa il nome e lo spazio dei nomi predefiniti per l'elemento wrapper e lo elabora insieme al contenuto (vedere la sezione precedente "Specifica del nome radice predefinito e dello spazio dei nomi").

Nell'esempio seguente viene mostrato come scrivere con un oggetto XmlDictionaryWriter.

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)

In questo modo viene generato codice XML simile al seguente.

<Person>  
  <Name>Jay Hamlin</Name>  
  <Address>123 Main St.</Address>  
</Person>  

PassaggioBy-Step di serializzazione

Usare i metodi WriteStartObject, WriteObjectContent e WriteEndObject per scrivere l'elemento finale, scrivere il contenuto dell'oggetto e chiudere rispettivamente l'elemento wrapper.

Nota

Non esistono sovraccarichi di questi metodi.

Questa serializzazione dettagliata include due usi comuni. Uno consiste nell'inserire contenuti come attributi o commenti tra WriteStartObject e WriteObjectContent, come illustrato nell'esempio seguente.

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)

In questo modo viene generato codice XML simile al seguente.

<Person serializedBy="myCode">  
  <Name>Jay Hamlin</Name>  
  <Address>123 Main St.</Address>  
</Person>  

Un altro uso comune consiste nell'evitare di usare WriteStartObject e WriteEndObject completamente e scrivere un elemento wrapper personalizzato (o anche ignorare completamente la scrittura di un wrapper), come illustrato nel codice seguente.

xdw.WriteStartElement("MyCustomWrapper");
dcs.WriteObjectContent(xdw, p);
xdw.WriteEndElement();
xdw.WriteStartElement("MyCustomWrapper")
dcs.WriteObjectContent(xdw, p)
xdw.WriteEndElement()

In questo modo viene generato codice XML simile al seguente.

<MyCustomWrapper>  
  <Name>Jay Hamlin</Name>  
  <Address>123 Main St.</Address>  
</MyCustomWrapper>  

Nota

L'uso della serializzazione sequenziale può comportare XML non valido per lo schema.

Deserializzazione

Le informazioni seguenti si applicano a qualsiasi classe che eredita da XmlObjectSerializer, incluse le DataContractSerializer classi e NetDataContractSerializer .

Il modo più semplice per deserializzare un oggetto consiste nel chiamare uno degli overload del ReadObject metodo. Sono disponibili tre overload, uno per la lettura con un XmlDictionaryReader, un XmlReader, o un Stream. Si noti che l'overload Stream crea un elemento testuale XmlDictionaryReader che non è protetto da alcuna quota e dovrebbe essere usato solo per leggere dati di cui ci si fida.

Si noti anche che l'oggetto restituito dal metodo ReadObject deve essere effettuato il cast al tipo appropriato.

Il codice seguente costruisce un'istanza di DataContractSerializer e un'istanza di XmlDictionaryReader, quindi deserializza un'istanza di Person.

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)

Prima di chiamare il ReadObject metodo , posizionare il lettore XML sull'elemento wrapper o su un nodo non di contenuto che precede l'elemento wrapper. A tale scopo, è possibile chiamare il metodo Read di XmlReader o della sua derivazione, e testare NodeType, come mostrato nel codice seguente.

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

Si noti che è possibile leggere gli attributi su questo elemento wrapper prima di passare il lettore a ReadObject.

Quando si usa uno degli overload semplici ReadObject, il deserializzatore cerca il nome e gli spazi dei nomi predefiniti nell'elemento wrapper (vedere la sezione precedente, "Impostare il nome radice e lo spazio dei nomi predefiniti") e solleva un'eccezione se trova un elemento sconosciuto. Nell'esempio precedente è previsto l'elemento <Person> wrapper. Viene chiamato il IsStartObject metodo per verificare che il lettore sia posizionato su un elemento denominato come previsto.

C'è un modo per disabilitare questo controllo del nome dell'elemento wrapper; alcuni overload del metodo ReadObject accettano il parametro booleano verifyObjectName, che è impostato su true per impostazione predefinita. Se impostato su false, il nome e lo spazio dei nomi dell'elemento wrapper vengono ignorati. Ciò è utile per la lettura del codice XML scritto usando il meccanismo di serializzazione dettagliato descritto in precedenza.

Uso di NetDataContractSerializer

La differenza principale tra DataContractSerializer e NetDataContractSerializer è che DataContractSerializer usa nomi di contratto dati, mentre NetDataContractSerializer restituisce nomi completi di assembly .NET Framework e di tipo nel XML serializzato. Ciò significa che gli stessi tipi devono essere condivisi tra gli endpoint di serializzazione e deserializzazione. Ciò significa che il meccanismo dei tipi noti non è necessario con NetDataContractSerializer perché i tipi esatti da deserializzare sono sempre noti.

Tuttavia, possono verificarsi diversi problemi:

  • Sicurezza. Viene caricato qualsiasi tipo trovato nell'XML in fase di deserializzazione. Questo può essere sfruttato per forzare il caricamento di tipi dannosi. L'uso di NetDataContractSerializer con dati non attendibili deve essere eseguito solo se viene usato un binder di serializzazione (usando la proprietà o il parametro del Binder costruttore). Il binder consente di caricare solo tipi sicuri. Il meccanismo Binder è identico a quello usato dai tipi nello spazio dei nomi System.Runtime.Serialization.

  • Controllo delle versioni. L'uso di nomi completi di tipi e assembly nel codice XML limita notevolmente la modalità di controllo delle versioni dei tipi. Non è possibile modificare i nomi dei tipi, gli spazi dei nomi, i nomi degli assembly e le versioni degli assembly. L'impostazione del parametro della proprietà o del costruttore su AssemblyFormat anziché sul valore predefinito di Simple consente di modificare la versione dell'assembly, ma non per i tipi di parametri generici.

  • Interoperabilità. Poiché i nomi di assembly e di tipo .NET Framework sono inclusi nel codice XML, le piattaforme diverse da .NET Framework non possono accedere ai dati risultanti.

  • Prestazione. La scrittura dei nomi di tipo e assembly aumenta significativamente le dimensioni del codice XML risultante.

Questo meccanismo è simile alla serializzazione binaria o SOAP usata dalla comunicazione remota di .NET Framework (in particolare, BinaryFormatter e SoapFormatter).

L'uso NetDataContractSerializer di è simile all'uso di DataContractSerializer, con le differenze seguenti:

  • I costruttori non richiedono di specificare un tipo di elemento radice. È possibile serializzare qualsiasi tipo con la stessa istanza di NetDataContractSerializer.

  • I costruttori non accettano un elenco di tipi noti. Il meccanismo dei tipi noti non è necessario se i nomi dei tipi vengono serializzati nel codice XML.

  • I costruttori non accettano un surrogato del contratto di dati. Accettano invece un ISurrogateSelector parametro, denominato surrogateSelector, che si mappa alla proprietà SurrogateSelector. Si tratta di un meccanismo surrogato legacy.

  • I costruttori accettano un parametro denominato assemblyFormat dell'oggetto FormatterAssemblyStyle che mappa alla proprietà AssemblyFormat. Come illustrato in precedenza, questo può essere usato per migliorare le funzionalità di controllo delle versioni del serializzatore. Questo è identico al FormatterAssemblyStyle meccanismo nella serializzazione binaria o SOAP.

  • I costruttori accettano un parametro StreamingContext chiamato context che viene mappato sulla proprietà Context. È possibile usarlo per passare informazioni ai tipi da serializzare. Questo utilizzo è identico a quello del StreamingContext meccanismo usato in altre System.Runtime.Serialization classi.

  • I Serialize metodi e Deserialize sono alias per i WriteObject metodi e ReadObject . Esistono per fornire un modello di programmazione più coerente con serializzazione binaria o SOAP.

Per altre informazioni su queste funzionalità, vedere Serializzazione binaria.

I formati XML che NetDataContractSerializer e DataContractSerializer utilizzano non sono normalmente compatibili. Ovvero, il tentativo di serializzare con uno di questi serializzatori e deserializzare con l'altro non è uno scenario supportato.

Si noti inoltre che NetDataContractSerializer non restituisce il tipo completo di .NET Framework e il nome dell'assembly per ogni nodo nell'oggetto grafico. Restituisce tali informazioni solo dove è ambiguo. Ovvero, produce risultati a livello di oggetto radice e per eventuali casi polimorfici.

Vedere anche