将数据从 Xamarin.Forms 应用属性字典迁移到 .NET MAUI 首选项
Xamarin.Forms 具有一个可用于存储数据的 Properties
字典,可使用 Application.Current.Properties
属性对其访问。 该字典使用 string
密钥并存储 object
值。 当应用暂停或关闭时,字典中的值将保存到设备,并在应用重新启动或从后台返回时加载。 有关属性字典的详细信息,请参阅属性字典。
在将在应用属性字典中存储数据的 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 应用项目的 Platforms\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 应用项目的 Platforms\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 应用项目的 Platforms\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);
}
}
}
PropertiesDeserializer
类的此 Windows 版本需要使用 DontSync
扩展方法。 下面代码展示了此扩展方法:
注意
要使用此代码,请将其添加到 .NET MAUI 应用项目 Platforms\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 首选项。
重要说明
请务必首先检查应用属性字典中是否存在密钥,然后再访问它,以防止发生意外错误。