Chi si avvicina al mondo delle Metro Style Apps in questo momento, probabilmente, fa uso smodato dei samples che si trovano al link:
http://code.msdn.microsoft.com/windowsapps/
Coloro che scaricano i samples in VB (ma mi sembra ci sia anche in C#), troveranno un interessante modulo per gestire i dati da salvare su isolated storage per la gestione, ad esempio, della sospensione.
Tale modulo si chiama SuspensionManager e utilizza un Dictionary(Of String, Object) per la memorizzazione dei dati da salvare in sessione.
Sono presenti, poi, due metodi per salvare e recupere il dictionary dall'isolated storage i quali utilizzano un DataContractSerializer per la serializzazione.
Per semplicità riporto il modulo presente nei samples:
- ' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- ' ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- ' THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- ' PARTICULAR PURPOSE.
- '
- ' Copyright (c) Microsoft Corporation. All rights reserved
- Imports System.IO
- Imports System.Runtime.Serialization
- Imports Windows.Storage
- Imports Windows.Storage.Streams
- Module SuspensionManager
- Private sessionState_ As New Dictionary(Of String, Object)
- Private knownTypes_ As List(Of Type) = New List(Of Type)
- Private Const filename As String = "_sessionState.xml"
- ' Provides access to the currect session state
- Public ReadOnly Property SessionState As Dictionary(Of String, Object)
- Get
- Return sessionState_
- End Get
- End Property
- ' Allows custom types to be added to the list of types that can be serialized
- Public ReadOnly Property KnownTypes As List(Of Type)
- Get
- Return knownTypes_
- End Get
- End Property
- ' Save the current session state
- Public Async Function SaveAsync() As Task
- ' Get the output stream for the SessionState file.
- Dim file As StorageFile = Await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting)
- Dim raStream As IRandomAccessStream = Await file.OpenAsync(FileAccessMode.ReadWrite)
- Using outStream As IOutputStream = raStream.GetOutputStreamAt(0)
- ' Serialize the Session State.
- Dim serializer As New DataContractSerializer(GetType(Dictionary(Of String, Object)))
- serializer.WriteObject(outStream.AsStreamForWrite, sessionState_)
- Await outStream.FlushAsync
- End Using
- End Function
- ' Restore the saved sesison state
- Public Async Function RestoreAsync() As Task
- ' Get the input stream for the SessionState file.
- Try
- Dim file As StorageFile = Await ApplicationData.Current.LocalFolder.GetFileAsync(filename)
- If file Is Nothing Then
- Exit Function
- End If
- Dim inStream As IInputStream = Await file.OpenSequentialReadAsync
- ' Deserialize the Session State.
- Dim serializer As New DataContractSerializer(GetType(Dictionary(Of String, Object)))
- sessionState_ = CType(serializer.ReadObject(inStream.AsStreamForRead), Dictionary(Of String, Object))
- Catch ex As Exception
- ' Restoring state is best-effort. If it fails, the app will just come up with a new session.
- End Try
- End Function
- End Module
A parte che, personalmente (ma è gusto personale, quindi opinabile), non amo i moduli vecchio stile, il modulo proposto negli esempi non permette di serializzare eventuali nostre classi.
Questo perchè è previsto l’attributo privato knownTypes_ di tipo List(Of Type) (con relativa properietà esposta) ma, di fatto, non ne viene fatto uso nel DataContractSerializer:
- ' Get the output stream for the SessionState file.
- Dim file As StorageFile = Await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting)
- Dim raStream As IRandomAccessStream = Await file.OpenAsync(FileAccessMode.ReadWrite)
- Using outStream As IOutputStream = raStream.GetOutputStreamAt(0)
- ' Serialize the Session State.
- Dim serializer As New DataContractSerializer(GetType(Dictionary(Of String, Object)))
- serializer.WriteObject(outStream.AsStreamForWrite, sessionState_)
- Await outStream.FlushAsync
- End Using
La modifica da apportare, quindi, per gestire le nostre classi (ovviamente purchè le stesse siano serializzabili) è di comunicare al DataContractSerializer che abbiamo dei tipi che deve conoscere:
- ' Get the output stream for the SessionState file.
- Dim file As StorageFile = Await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting)
- Dim raStream As IRandomAccessStream = Await file.OpenAsync(FileAccessMode.ReadWrite)
- Using outStream As IOutputStream = raStream.GetOutputStreamAt(0)
- ' Serialize the Session State.
- Dim serializer As New DataContractSerializer(GetType(Dictionary(Of String, Object)), knownTypes_)
- serializer.WriteObject(outStream.AsStreamForWrite, sessionState_)
- Await outStream.FlushAsync
- End Using
Per poter, dunque, utilizzare liberamente le nostre classi potremmo, una tantum, aggiungere i nostri tipi ed essere sicuri che il tutto funzioni:
- SuspensionManager.Instance.KnownTypes.Add(GetType(Contact))
In allegato al post trovate la solution per Visual Studio 11 Beta con la classe e una modesta interfaccia di prova.
Commenti