將數據從 Xamarin.Forms 應用程式屬性字典遷移至 .NET MAUI 喜好設定

Xamarin.Forms 有一個 Properties 字典,可用來儲存數據,並使用 屬性來存取 Application.Current.Properties 。 此字典使用 string 索引鍵並儲存 object 值。 字典中的值會在應用程式暫停或關閉時儲存至裝置,並在應用程式重新啟動或從背景傳回時載入。 如需屬性字典的詳細資訊,請參閱 屬性字典

將 Xamarin.Forms 應用程式將資料儲存在應用程式屬性字典中的 Xamarin.Forms 應用程式移轉至 .NET MAUI 時,您應該將此數據遷移至 .NET MAUI 喜好設定。 這可以透過 LegacyApplication 類別和協助程序類別來完成,本文中會說明此類別。 這個類別可讓您在 Android、iOS 和 Windows 上使用 .NET MAUI 應用程式,從使用舊版 Xamarin.Forms 應用程式所建立的應用程式屬性字典讀取數據。 如需 .NET MAUI 喜好設定的詳細資訊,請參閱 喜好設定

重要

沒有 API 可存取 .NET MAUI 中的應用程式屬性字典。

存取舊版應用程式屬性數據

下列程式代碼顯示 類別 LegacyApplication ,可讓您存取 Xamarin.Forms 應用程式所建立的應用程式屬性資料:

注意

若要使用此程式碼,請將它新增至 .NET MAUI 應用程式項目中名為 LegacyApplication 的類別。

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

在Android上,類別 LegacyApplication 會使用 PropertiesDeserializer 類別,從應用程式屬性字典檔案還原串行化數據。 下列程式碼顯示 PropertiesDeserializer 類別:

注意

若要使用此程式代碼,請將它新增至 .NET MAUI 應用程式專案的 Platform\Android 資料夾中名為 PropertiesDeserializer的類別。

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

在 iOS 上,類別 LegacyApplication 會使用 PropertiesDeserializer 類別,從應用程式屬性字典檔案還原串行化數據。 下列程式碼顯示 PropertiesDeserializer 類別:

注意

若要使用此程式碼,請將它新增至 .NET MAUI 應用程式專案的 Platform\iOS 資料夾中名為 PropertiesDeserializer的類別。

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

在 Windows 上,類別 LegacyApplication 會使用 PropertiesDeserializer 類別從應用程式屬性字典檔案還原串行化數據。 下列程式碼顯示 PropertiesDeserializer 類別:

注意

若要使用此程式碼,請將它新增至 .NET MAUI 應用程式專案的 Platform\Windows 資料夾中名為 PropertiesDeserializer的類別。

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);
        }
    }
}

這個 Windows 版本的 PropertiesDeserializer 類別需要 DontSync 擴充方法。 下列程式代碼顯示此擴充方法:

注意

若要使用此程式碼,請將它新增至 .NET MAUI 應用程式專案的 Platform\Windows 資料夾中名為 Extensions的類別。

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);
    }
}

取用舊版應用程式屬性數據

類別 LegacyApplication 可用來取用應用程式屬性字典中的數據,在 Android、iOS 和 Windows 上,使用您先前的 Xamarin.Forms 版本所建立:

#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

這個範例示範如何使用 LegacyApplication 類別從應用程式屬性字典讀取值,然後將值寫入 .NET MAUI 喜好設定。

重要

請務必先檢查應用程式屬性字典中是否有索引鍵,再存取它,以避免發生非預期的錯誤。