Condividi tramite


Serializzazione a tolleranza di versione (VTS, Version Tolerant Serialization)

Nelle versioni 1.0 e 1.1 di .NET Framework, la creazione di tipi serializzabili che possono essere riutilizzati da una versione di un'applicazione a quella successiva potrebbe risultare problematica. Se un tipo è stato modificato mediante l'aggiunta di campi, possono verificarsi i problemi seguenti:

  • Le versioni precedenti di un'applicazione generano eccezioni quando viene richiesto di deserializzare le versioni nuove del tipo precedente.

  • Le versioni più recenti di un'applicazione generano eccezioni durante la deserializzazione di versioni precedenti di un tipo con dati mancanti.

La serializzazione a tolleranza di versione (VTS, Version Tolerant Serialization) è un gruppo di funzionalità introdotto in .NET Framework 2.0 che rende più semplice modificare successivamente i tipi serializzabili. Le funzionalità di VTS in particolare sono attive per le classi alle quali è stato applicato l'attributo SerializableAttribute. VTS rende possibile aggiungere nuovi campi a tali classi senza influire sulla compatibilità con altre versioni del tipo. Per un esempio di applicazione, vedere Version Tolerant Serialization Technology Sample.

Le funzionalità di VTS vengono attivate quando si utilizza BinaryFormatter. Tutte le funzionalità, tranne la tolleranza dei dati estranei, vengono inoltre attivate quando si utilizza SoapFormatter. Per ulteriori informazioni sull'utilizzo di queste classi per la serializzazione, vedere Serializzazione binaria.

Nota

La funzionalità di tolleranza dei dati estranei per BinaryFormatter potrà essere disponibile per .NET Framework 1.1 come patch in futuro.

Elenco delle funzionalità

Nel gruppo di funzionalità sono incluse:

  • Tolleranza dei dati estranei o imprevisti. Questa funzionalità consente alle versioni più recenti del tipo di inviare dati a versioni precedenti.

  • Tolleranza dei dati facoltativi mancanti. Questa funzionalità consente a versioni precedenti di inviare dati a versioni più recenti.

  • Callback di serializzazione. Questa funzionalità consente l'impostazione intelligente di valori predefiniti quando mancano i dati.

È inoltre disponibile una funzionalità che consente di dichiarare quando viene aggiunto un nuovo campo facoltativo. Si tratta della proprietà VersionAdded dell'attributo OptionalFieldAttribute.

Queste funzionalità vengono descritte dettagliatamente di seguito.

Tolleranza dei dati estranei o imprevisti

Nelle versioni precedenti qualsiasi dato estraneo o imprevisto generava eccezioni durante la deserializzazione. Con VTS, nella stessa situazione, i dati estranei o imprevisti non generano eccezioni ma vengono ignorati. In questo modo le applicazioni che utilizzano versioni più recenti di un tipo, ovvero le versioni che includono più campi, possono inviare informazioni ad applicazioni che si aspettano versioni precedenti dello stesso tipo.

Nell'esempio seguente, i dati aggiuntivi contenuti in CountryField della versione 2.0 della classe Address vengono ignorati quando un'applicazione meno recente deserializza la versione più recente.

// 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 dei dati mancanti

L'applicazione dell'attributo OptionalFieldAttribute ai campi consente di contrassegnarli come facoltativi. Durante la deserializzazione, se mancano dati facoltativi, il modulo di gestione della serializzazione li ignora e non genera eccezioni. In questo modo, le applicazioni che si aspettano versioni precedenti di un tipo possono inviare dati ad applicazioni che si aspettano versioni più recenti dello stesso tipo.

Nell'esempio seguente viene illustrata la versione 2.0 della classe Address con il campo CountryField contrassegnato come facoltativo. Se un'applicazione meno recente invia la versione 1 a un'applicazione più recente che si aspetta la versione 2.0, i dati mancanti vengono ignorati.

[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 serializzazione

I callback di serializzazione sono un meccanismo che inserisce hook in quattro punti del processo di serializzazione/deserializzazione.

Attributo Chiamata al metodo associato Utilizzo

OnDeserializingAttribute

Prima della deserializzazione.*

Inizializzare valori predefiniti per campi facoltativi.

OnDeserializedAttribute

Dopo la deserializzazione.

Correggere valori di campi facoltativi in base al contenuto di altri campi.

OnSerializingAttribute

Prima della serializzazione.

Preparare la serializzazione. Ad esempio, creare strutture di dati facoltativi.

OnSerializedAttribute

Dopo la serializzazione.

Registrare eventi di serializzazione.

* Questo callback viene richiamato prima del costruttore della deserializzazione, se presente.

Utilizzo di callback

Per utilizzare i callback, applicare l'attributo appropriato a un metodo che accetta un parametro StreamingContext. È possibile contrassegnare solo un metodo per classe con ognuno di questi attributi. Ad esempio:

[OnDeserializing]
private void SetCountryRegionDefault(StreamingContext sc)
{
    CountryField = "Japan";
}
[OnDeserializing]
private void SetCountryRegionDefault(StreamingContext sc)
{
    CountryField = "Japan";
}

L'utilizzo previsto per questi metodi è il controllo delle versioni. Durante la deserializzazione, un campo facoltativo potrebbe non venire inizializzato correttamente se mancano i dati corrispondenti. Questa situazione può essere corretta creando il metodo che assegna il valore appropriato, quindi applicando a tale metodo l'attributo OnDeserializingAttribute o OnDeserializedAttribute.

Nell'esempio seguente viene illustrato il metodo nel contesto di un tipo. Se una versione precedente di un'applicazione invia un'istanza della classe Address a una versione successiva dell'applicazione, mancheranno i dati del campo CountryField. Dopo la deserializzazione, tuttavia, il campo sarà impostato sul valore predefinito "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à VersionAdded

OptionalFieldAttribute ha la proprietà VersionAdded. Questa proprietà non viene utilizzata nella versione 2.0 di .NET Framework. È tuttavia importante impostarla correttamente, per assicurarsi che il tipo sia compatibile con i moduli di gestione della serializzazione futuri.

La proprietà indica a quale versione di un tipo è stato aggiunto un campo specifico. È consigliabile aumentarla esattamente di uno (a partire da 2) ogni volta che il tipo viene modificato, come illustrato nell'esempio seguente:

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

Procedure consigliate

Per assicurare il comportamento corretto del controllo delle versioni, seguire queste regole quando si modifica un tipo da una versione all'altra:

  • Non rimuovere un campo serializzato.

  • Non applicare a un campo l'attributo NonSerializedAttribute se non è stato applicato al campo nella versione precedente.

  • Non modificare il nome o il tipo del campo serializzato.

  • Quando si aggiunge un nuovo campo serializzato, applicare l'attributo OptionalFieldAttribute.

  • Quando si rimuove un attributo NonSerializedAttribute da un campo non serializzabile in una versione precedente, applicare l'attributo OptionalFieldAttribute.

  • Per tutti i campi facoltativi, impostare valori predefiniti significativi utilizzando callback di serializzazione, a meno che 0 o null non siano accettabili come valori predefiniti.

Per assicurarsi che un tipo sia compatibile con i moduli di gestione della serializzazione futuri, seguire le indicazioni seguenti:

  • Impostare sempre correttamente la proprietà VersionAdded sull'attributo OptionalFieldAttribute.

  • Evitare le diramazioni nel controllo delle versioni.

Vedere anche

Riferimenti

SerializableAttribute
BinaryFormatter
SoapFormatter
VersionAdded
OptionalFieldAttribute
OnDeserializingAttribute
OnDeserializedAttribute
OnDeserializingAttribute
OnSerializedAttribute
StreamingContext
NonSerializedAttribute

Altre risorse

Serializzazione binaria