Serializzazione indipendente dalla versioneVersion tolerant serialization

Nelle versioni 1.0 e 1.1 di .NET Framework, la creazione di tipi serializzabili riutilizzabili da una versione di un'applicazione alla versione successiva risultava problematica.In version 1.0 and 1.1 of the .NET Framework, creating serializable types that would be reusable from one version of an application to the next was problematic. Se un tipo veniva modificato aggiungendo campi aggiuntivi, si verificavano i seguenti problemi:If a type was modified by adding extra fields, the following problems would occur:

  • Le versioni precedenti di un'applicazione avrebbero generato eccezioni durante la richiesta di deserializzazione delle nuove versioni del tipo obsoleto.Older versions of an application would throw exceptions when asked to deserialize new versions of the old type.

  • Le versioni più recenti di un'applicazione avrebbero generato eccezioni durante la deserializzazione delle versioni precedenti di un tipo con dati mancanti.Newer versions of an application would throw exceptions when deserializing older versions of a type with missing data.

La Serializzazione a tolleranza di versione (VTS, Version Tolerant Serialization) è un set di funzionalità introdotto in .NET Framework 2.0 che semplifica, nel tempo, la modifica dei tipi serializzabili.Version Tolerant Serialization (VTS) is a set of features introduced in .NET Framework 2.0 that makes it easier, over time, to modify serializable types. In particolare, le funzionalità VTS vengono abilitate per le classi alle quali è stato applicato l'attributo SerializableAttribute, inclusi i tipi generici.Specifically, the VTS features are enabled for classes to which the SerializableAttribute attribute has been applied, including generic types. VTS rende possibile l'aggiunta di nuovi campi a tali classi senza compromettere la compatibilità con le altre versioni del tipo.VTS makes it possible to add new fields to those classes without breaking compatibility with other versions of the type. Per un'applicazione di esempio funzionante, vedere Esempio di tecnologia di serializzazione indipendente dalla versione.For a working sample application, see Version Tolerant Serialization Technology Sample.

Le funzionalità VTS vengono abilitate durante l'utilizzo di BinaryFormatter.The VTS features are enabled when using the BinaryFormatter. Inoltre, durante l'utilizzo di SoapFormatter, sono abilitate tutte le funzionalità salvo la tolleranza di dati estranei.Additionally, all features except extraneous data tolerance are also enabled when using the SoapFormatter. Per altre informazioni sull'uso di queste classi per la serializzazione, vedere Serializzazione binaria.For more information about using these classes for serialization, see Binary Serialization.

Avviso

La serializzazione binaria può rappresentare un pericolo.Binary serialization can be dangerous. Non deserializzare mai dati da un'origine non attendibile e non eseguire il round trip per i dati serializzati verso sistemi non sotto il proprio controllo.Never deserialize data from an untrusted source and never round-trip serialized data to systems not under your control.

Elenco delle funzionalitàFeature list

Il set di funzionalità comprende quanto segue:The set of features includes the following:

  • Tolleranza di dati estranei o imprevisti.Tolerance of extraneous or unexpected data. Consente a versioni più recenti del tipo di inviare dati alle versioni precedenti.This enables newer versions of the type to send data to older versions.

  • Tolleranza di dati facoltativi mancanti.Tolerance of missing optional data. Consente a versioni precedenti di inviare dati alle versioni più recenti.This enables older versions to send data to newer versions.

  • Callback di serializzazione.Serialization callbacks. Consente l'impostazione intelligente del valore predefinito nei casi in cui dei dati siano mancanti.This enables intelligent default value setting in cases where data is missing.

In aggiunta, è presente una funzionalità che consente di dichiarare l'aggiunta di un nuovo campo facoltativo.In addition, there is a feature for declaring when a new optional field has been added. Questa è la proprietà VersionAdded dell'attributo OptionalFieldAttribute.This is the VersionAdded property of the OptionalFieldAttribute attribute.

Queste funzionalità vengono discusse in dettaglio di seguito.These features are discussed in greater detail below.

Tolleranza di dati estranei o imprevistiTolerance of extraneous or unexpected data

In passato, durante la serializzazione, la presenza di dati estranei o imprevisti generava eccezioni.In the past, during deserialization, any extraneous or unexpected data caused exceptions to be thrown. Con VTS, nella stessa situazione, eventuali dati estranei o imprevisti vengono ignorati piuttosto che generare eccezioni.With VTS, in the same situation, any extraneous or unexpected data is ignored instead of causing exceptions to be thrown. Ciò consente alle applicazioni che utilizzano versioni più recenti di un tipo (ovvero una versione che include più campi) di inviare informazioni alle applicazioni che prevedono versioni precedenti dello stesso tipo.This enables applications that use newer versions of a type (that is, a version that includes more fields) to send information to applications that expect older versions of the same type.

Nell'esempio riportato di seguito, i dati aggiuntivi contenuti in CountryField della versione 2.0 della classe Address vengono ignorati nel momento in cui un'applicazione precedente deserializza la versione più recente.In the following example, the extra data contained in the CountryField of version 2.0 of the Address class is ignored when an older application deserializes the newer version.

// Version 1 of the Address class.  
[Serializable]  
public class Address  
{  
    public string Street;  
    public string City;  
}  
// Version 2.0 of the Address class.  
[Serializable]  
public class Address  
{  
    public string Street;  
    public string City;  
    // The older application ignores this data.  
    public string CountryField;  
}  
' Version 1 of the Address class.  
<Serializable> _  
Public Class Address  
    Public Street As String  
    Public City As String  
End Class  
  
' Version 2.0 of the Address class.  
<Serializable> _  
Public Class Address  
    Public Street As String  
    Public City As String  
    ' The older application ignores this data.  
    Public CountryField As String  
End Class  

Tolleranza di dati mancantiTolerance of missing data

I campi possono essere contrassegnati come facoltativi applicando ad essi l'attributo OptionalFieldAttribute.Fields can be marked as optional by applying the OptionalFieldAttribute attribute to them. Durante la deserializzazione, se i dati facoltativi risultano mancanti, il motore di serializzazione ignora tale assenza e non genera eccezioni.During deserialization, if the optional data is missing, the serialization engine ignores the absence and does not throw an exception. In tal modo, le applicazioni che prevedono versioni precedenti di un tipo, possono inviare dati ad applicazioni che prevedono versioni più recenti dello stesso tipo.Thus, applications that expect older versions of a type can send data to applications that expect newer versions of the same type.

Nell'esempio riportato di seguito viene mostrata la versione 2.0 della classe Address con il campo CountryField contrassegnato come facoltativo.The following example shows version 2.0 of the Address class with the CountryField field marked as optional. Se un'applicazione precedente invia la versione 1 a un'applicazione più recente che prevede la versione 2.0, l'assenza dei dati viene ignorata.If an older application sends version 1 to a newer application that expects version 2.0, the absence of the data is ignored.

[Serializable]  
public class Address  
{  
    public string Street;  
    public string City;  
  
    [OptionalField]  
    public string CountryField;  
}  
<Serializable> _  
Public Class Address  
    Public Street As String  
    Public City As String  
  
    <OptionalField> _  
    Public CountryField As String  
End Class  

Callback di serializzazioneSerialization callbacks

I callback di serializzazione rappresentano un meccanismo che fornisce hook nel processo di serializzazione/deserializzazione in quattro punti.Serialization callbacks are a mechanism that provides hooks into the serialization/deserialization process at four points.

AttributoAttribute Quando viene chiamato il metodo associatoWhen the Associated Method is Called Utilizzo tipicoTypical Use
OnDeserializingAttribute Prima della deserializzazione.*Before deserialization.* Inizializzare i valori predefiniti per i campi facoltativi.Initialize default values for optional fields.
OnDeserializedAttribute Dopo la deserializzazione.After deserialization. Correggere i valori dei campi facoltativi in base al contenuto di altri campi.Fix optional field values based on contents of other fields.
OnSerializingAttribute Prima della serializzazione.Before serialization. Preparare per la serializzazione.Prepare for serialization. Ad esempio, la creazione di strutture di dati facoltativi.For example, create optional data structures.
OnSerializedAttribute Dopo la serializzazione.After serialization. Registrare gli eventi di serializzazione.Log serialization events.

* Questo callback viene richiamato prima del costruttore di deserializzazione, se presente.* This callback is invoked before the deserialization constructor, if one is present.

Uso dei callbackUsing callbacks

Per utilizzare i callback, applicare l'attributo appropriato a un metodo che accetta un parametro StreamingContext.To use callbacks, apply the appropriate attribute to a method that accepts a StreamingContext parameter. È possibile contrassegnare solo uno metodo per classe con ciascuno di questi attributi.Only one method per class can be marked with each of these attributes. Ad esempio:For example:

[OnDeserializing]  
private void SetCountryRegionDefault(StreamingContext sc)  
{  
    CountryField = "Japan";  
}  
<OnDeserializing>  
Private Sub SetCountryRegionDefault(StreamingContext sc)  
    CountryField = "Japan";  
End Sub  

L'utilizzo di questi metodi è destinato al controllo la versione.The intended use of these methods is for versioning. Durante la deserializzazione, un campo facoltativo potrebbe non essere inizializzato correttamente nel caso in cui i dati del campo risultino mancanti.During deserialization, an optional field may not be correctly initialized if the data for the field is missing. Ciò può essere corretto creando il metodo che assegna il valore appropriato e quindi applicando l'attributo OnDeserializingAttribute o OnDeserializedAttribute al metodo.This can be corrected by creating the method that assigns the correct value, then applying either the OnDeserializingAttribute or OnDeserializedAttribute attribute to the method.

Nell'esempio riportato di seguito, viene mostrato il metodo nel contesto di un tipo.The following example shows the method in the context of a type. Se una versione precedente di un'applicazione invia un'istanza della classe Address a una versione più recente dell'applicazione, i dati del campo CountryField risulteranno mancanti.If an earlier version of an application sends an instance of the Address class to a later version of the application, the CountryField field data will be missing. Tuttavia dopo la deserializzazione, il campo verrà impostato su un valore predefinito "Giappone".But after deserialization, the field will be set to a default value "Japan."

[Serializable]  
public class Address  
{  
    public string Street;  
    public string City;  
    [OptionalField]  
    public string CountryField;  
  
    [OnDeserializing]  
    private void SetCountryRegionDefault (StreamingContext sc)  
    {  
        CountryField = "Japan";  
    }  
}  
<Serializable> _  
Public Class Address  
    Public Street As String  
    Public City As String  
    <OptionalField> _  
    Public CountryField As String  
  
    <OnDeserializing> _  
    Private Sub SetCountryRegionDefault(StreamingContext sc)  
        CountryField = "Japan";  
    End Sub  
End Class  

Proprietà VersionAddedThe VersionAdded property

L'oggetto OptionalFieldAttribute ha la proprietà VersionAdded.The OptionalFieldAttribute has the VersionAdded property. In .NET Framework versione 2.0 tale proprietà non viene usata.In version 2.0 of the .NET Framework, this isn't used. È tuttavia importante impostare correttamente questa proprietà in modo da essere certi che il tipo sia compatibile con i motori di serializzazione futuri.However, it's important to set this property correctly to ensure that the type will be compatible with future serialization engines.

La proprietà indica quale versione di un tipo di un determinato campo è stata aggiunta.The property indicates which version of a type a given field has been added. È necessario che venga incrementato esattamente di uno (a partire da 2) ogni volta che viene modificato il tipo, come mostra l'esempio riportato di seguito:It should be incremented by exactly one (starting at 2) every time the type is modified, as shown in the following example:

// Version 1.0  
[Serializable]  
public class Person  
{  
    public string FullName;  
}  
  
// Version 2.0  
[Serializable]  
public class Person  
{  
    public string FullName;  
  
    [OptionalField(VersionAdded = 2)]  
    public string NickName;  
    [OptionalField(VersionAdded = 2)]  
    public DateTime BirthDate;  
}  
  
// Version 3.0  
[Serializable]  
public class Person  
{  
    public string FullName;  
  
    [OptionalField(VersionAdded=2)]  
    public string NickName;  
    [OptionalField(VersionAdded=2)]  
    public DateTime BirthDate;  
  
    [OptionalField(VersionAdded=3)]  
    public int Weight;  
}  
' Version 1.0  
<Serializable> _  
Public Class Person  
    Public FullName  
End Class  
  
' Version 2.0  
<Serializable> _  
Public Class Person  
    Public FullName As String  
  
    <OptionalField(VersionAdded := 2)> _  
    Public NickName As String  
    <OptionalField(VersionAdded := 2)> _  
    Public BirthDate As DateTime  
End Class  
  
' Version 3.0  
<Serializable> _  
Public Class Person  
    Public FullName As String  
  
    <OptionalField(VersionAdded := 2)> _  
    Public NickName As String  
    <OptionalField(VersionAdded := 2)> _  
    Public BirthDate As DateTime  
  
    <OptionalField(VersionAdded := 3)> _  
    Public Weight As Integer  
End Class  

SerializationBinderSerializationBinder

In alcuni casi potrebbe essere necessario controllare le classi da serializzare e deserializzare ad esempio perché sono richieste versioni diverse della classe sul server e sul client.Some users may need to control which class to serialize and deserialize because a different version of the class is required on the server and client. SerializationBinder è una classe astratta usata per controllare i tipi effettivi usati durante la serializzazione e la deserializzazione.SerializationBinder is an abstract class used to control the actual types used during serialization and deserialization. Per utilizzare questa classe, derivare una classe da SerializationBinder ed eseguire l'override dei metodi BindToName e BindToType,To use this class, derive a class from SerializationBinder and override the BindToName and BindToType methods. Per altre informazioni, vedere controllo di serializzazione e deserializzazione con SerializationBinder.For more information, see Controlling Serialization and Deserialization with SerializationBinder.

Procedure consigliateBest practices

Per essere certi del comportamento corretto del controllo della versione, attenersi a queste regole durante la modifica di un tipo da una versione a un'altra:To ensure proper versioning behavior, follow these rules when modifying a type from version to version:

  • Non rimuovere mai un campo serializzato.Never remove a serialized field.

  • Non applicare mai l'attributo NonSerializedAttribute a un campo se l'attributo non è stato applicato al campo nella versione precedente.Never apply the NonSerializedAttribute attribute to a field if the attribute was not applied to the field in the previous version.

  • Non modificare mai il nome o il tipo di un campo serializzato.Never change the name or the type of a serialized field.

  • Quando si aggiunge un nuovo campo serializzato, applicare l'attributo OptionalFieldAttribute.When adding a new serialized field, apply the OptionalFieldAttribute attribute.

  • Quando si rimuove un attributo NonSerializedAttribute da un campo (non serializzabile in una versione precedente), applicare l'attributo OptionalFieldAttribute.When removing a NonSerializedAttribute attribute from a field (that was not serializable in a previous version), apply the OptionalFieldAttribute attribute.

  • Per tutti i campi facoltativi, impostare valori predefiniti significativi usando callback di serializzazione, a meno che non risultino accettabili 0 o Null come valori predefiniti.For all optional fields, set meaningful defaults using the serialization callbacks unless 0 or null as defaults are acceptable.

Per essere certi che un tipo sia compatibile con i motori di serializzazione futuri, seguire le linee guida riportate di seguito:To ensure that a type will be compatible with future serialization engines, follow these guidelines:

  • Impostare sempre la proprietà VersionAdded sull'attributo OptionalFieldAttribute in modo corretto.Always set the VersionAdded property on the OptionalFieldAttribute attribute correctly.

  • Evitare controlli di versione sottoposti a branching.Avoid branched versioning.

Vedere ancheSee also