Migrar dados do dicionário de propriedades do aplicativo Xamarin.Forms para as preferências do .NET MAUI

Xamarin.Forms tem um Properties dicionário que pode ser usado para armazenar dados e que é acessado usando a Application.Current.Properties propriedade. Esse dicionário usa uma chave string e armazena um valor de object. Os valores no dicionário são salvos no dispositivo quando um aplicativo é pausado ou desligado e carregados quando um aplicativo é reiniciado ou retorna do plano de fundo. Para obter mais informações sobre o dicionário de propriedades, consulte Dicionário de propriedades.

Ao migrar um aplicativo Xamarin.Forms que armazena dados no dicionário de propriedades do aplicativo para o .NET MAUI, você deve migrar esses dados para as preferências do .NET MAUI. Isso pode ser feito com a classe e as LegacyApplication classes auxiliares, que são apresentadas neste artigo. Essa classe permite que seu aplicativo .NET MAUI no Android, iOS e Windows leia dados do dicionário de propriedades do aplicativo que foi criado com uma versão anterior do Xamarin.Forms do seu aplicativo. Para obter mais informações sobre as preferências do .NET MAUI, consulte Preferências.

Importante

Não há API para acessar o dicionário de propriedades do aplicativo no .NET MAUI.

Acessar dados de propriedades de aplicativos herdados

O código a seguir mostra a LegacyApplication classe, que fornece acesso aos dados de propriedades do aplicativo criados pelo aplicativo Xamarin.Forms:

Observação

Para usar esse código, adicione-o a uma classe nomeada LegacyApplication em seu projeto de aplicativo .NET MAUI.

namespace MigrationHelpers;

public class LegacyApplication
{
    readonly PropertiesDeserializer deserializer;
    Task<IDictionary<string, object>>? propertiesTask;

    static LegacyApplication? current;
    public static LegacyApplication? Current
    {
        get
        {
            current ??= (LegacyApplication)Activator.CreateInstance(typeof(LegacyApplication));
            return current;
        }
    }

    public LegacyApplication()
    {
        deserializer = new PropertiesDeserializer();
    }

    public IDictionary<string, object> Properties
    {
        get
        {
            propertiesTask ??= GetPropertiesAsync();
            return propertiesTask.Result;
        }
    }

    async Task<IDictionary<string, object>> GetPropertiesAsync()
    {
        IDictionary<string, object> properties = await deserializer.DeserializePropertiesAsync().ConfigureAwait(false);
        properties ??= new Dictionary<string, object>(4);
        return properties;
    }
}

Android

No Android, a classe usa a LegacyApplicationPropertiesDeserializer classe para desserializar dados do arquivo de dicionário de propriedades do aplicativo. O código a seguir mostra a classe PropertiesDeserializer:

Observação

Para usar esse código, adicione-o a uma classe nomeada PropertiesDeserializer na pasta Platforms\Android do seu projeto de aplicativo .NET MAUI.

using System.Diagnostics;
using System.IO.IsolatedStorage;
using System.Runtime.Serialization;
using System.Xml;

namespace MigrationHelpers;

public class PropertiesDeserializer
{
    const string PropertyStoreFile = "PropertyStore.forms";

    public Task<IDictionary<string, object>> DeserializePropertiesAsync()
    {
        // Deserialize property dictionary to local storage
        return Task.Run(() =>
        {
            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (!store.FileExists(PropertyStoreFile))
                    return null;

                using (IsolatedStorageFileStream stream = store.OpenFile(PropertyStoreFile, FileMode.Open, FileAccess.Read))
                using (XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
                {
                    if (stream.Length == 0)
                        return null;

                    try
                    {
                        var dcs = new DataContractSerializer(typeof(Dictionary<string, object>));
                        return (IDictionary<string, object>)dcs.ReadObject(reader);
                    }
                    catch (Exception e)
                    {
                        Debug.WriteLine("Could not deserialize properties: " + e.Message);
                        Console.WriteLine($"PropertyStore Exception while reading Application properties: {e}");
                    }
                }
            }
            return null;
        });
    }
}

iOS

No iOS, a classe usa a LegacyApplicationPropertiesDeserializer classe para desserializar dados do arquivo de dicionário de propriedades do aplicativo. O código a seguir mostra a classe PropertiesDeserializer:

Observação

Para usar esse código, adicione-o a uma classe nomeada PropertiesDeserializer na pasta Platforms\iOS do seu projeto de aplicativo .NET MAUI.

using System.Diagnostics;
using System.IO.IsolatedStorage;
using System.Runtime.Serialization;
using System.Xml;

namespace MigrationHelpers;

public class PropertiesDeserializer
{
    const string PropertyStoreFile = "PropertyStore.forms";

    public Task<IDictionary<string, object>> DeserializePropertiesAsync()
    {
        // Deserialize property dictionary to local storage
        return Task.Run(() =>
        {
            using (var store = IsolatedStorageFile.GetUserStoreForApplication())
            using (var stream = store.OpenFile(PropertyStoreFile, System.IO.FileMode.OpenOrCreate))
            using (var reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
            {
                if (stream.Length == 0)
                    return null;

                try
                {
                    var dcs = new DataContractSerializer(typeof(Dictionary<string, object>));
                    return (IDictionary<string, object>)dcs.ReadObject(reader);
                }
                catch (Exception e)
                {
                    Debug.WriteLine("Could not deserialize properties: " + e.Message);
                    Console.WriteLine($"PropertyStore Exception while reading Application properties: {e}");
                }
            }
            return null;
        });
    }
}

Windows

No Windows, a classe usa a LegacyApplicationPropertiesDeserializer classe para desserializar dados do arquivo de dicionário de propriedades do aplicativo. O código a seguir mostra a classe PropertiesDeserializer:

Observação

Para usar esse código, adicione-o a uma classe nomeada PropertiesDeserializer na pasta Platforms\Windows do seu projeto de aplicativo .NET MAUI.

using System.Diagnostics;
using System.Runtime.Serialization;
using Windows.Storage;

namespace MigrationHelpers;

public class PropertiesDeserializer
{
    const string PropertyStoreFile = "PropertyStore.forms";

    public async Task<IDictionary<string, object>> DeserializePropertiesAsync()
    {
        try
        {
            StorageFile file = await ApplicationData.Current.RoamingFolder.GetFileAsync(PropertyStoreFile).DontSync();
            using (Stream stream = (await file.OpenReadAsync().DontSync()).AsStreamForRead())
            {
                if (stream.Length == 0)
                    return new Dictionary<string, object>(4);

                try
                {
                    var serializer = new DataContractSerializer(typeof(IDictionary<string, object>));
                    return (IDictionary<string, object>)serializer.ReadObject(stream);
                }
                catch (Exception e)
                {
                    Debug.WriteLine("Could not deserialize properties: " + e.Message);
                    Console.WriteLine($"PropertyStore Exception while reading Application properties: {e}");
                }
                return null;
            }
        }
        catch (FileNotFoundException)
        {
            return new Dictionary<string, object>(4);
        }
    }
}

Esta versão do Windows da classe requer o PropertiesDeserializerDontSync método de extensão. O código a seguir mostra esse método de extensão:

Observação

Para usar esse código, adicione-o a uma classe nomeada Extensions na pasta Platforms\Windows do seu projeto de aplicativo .NET MAUI.

using System.Runtime.CompilerServices;
using Windows.Foundation;

namespace MigrationHelpers;

internal static class Extensions
{
    public static ConfiguredTaskAwaitable<T> DontSync<T>(this IAsyncOperation<T> self)
    {
        return self.AsTask().ConfigureAwait(false);
    }
}

Consumir dados de propriedade de aplicativos herdados

A LegacyApplication classe pode ser usada para consumir dados do dicionário de propriedades do aplicativo, no Android, iOS e Windows, que foi criado com uma versão anterior do Xamarin.Forms do seu aplicativo:

#if ANDROID || IOS || WINDOWS
using MigrationHelpers;
...

int id;
if (LegacyApplication.Current.Properties.ContainsKey("id"))
{
    id = (int)LegacyApplication.Current.Properties["id"];
    Preferences.Set("id", id);
}
#endif

Este exemplo mostra o uso da classe para ler um valor do dicionário de propriedades do aplicativo e, em seguida, gravar o LegacyApplication valor nas preferências do .NET MAUI.

Importante

Sempre verifique a presença da chave no dicionário de propriedades do aplicativo antes de acessá-lo, para evitar erros inesperados.