From 240b6a3e44f103ad069fb7643b7a9e092d72bcaa Mon Sep 17 00:00:00 2001 From: Shane Weaver Date: Mon, 26 Apr 2021 14:49:58 -0700 Subject: [PATCH 1/3] Updates to baseRoamingSettingsDataStore so serializization/deserialization is more consistent --- .../BaseRoamingSettingsDataStore.cs | 84 ++++++++++++------- 1 file changed, 52 insertions(+), 32 deletions(-) diff --git a/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/BaseRoamingSettingsDataStore.cs b/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/BaseRoamingSettingsDataStore.cs index 3498b77..28c77d9 100644 --- a/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/BaseRoamingSettingsDataStore.cs +++ b/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/BaseRoamingSettingsDataStore.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using Microsoft.Toolkit.Uwp.Helpers; using Windows.Storage; @@ -109,15 +110,7 @@ public T Read(string key, T @default = default) { if (Cache != null && Cache.TryGetValue(key, out object value)) { - try - { - return Serializer.Deserialize((string)value); - } - catch - { - // Primitive types can't be deserialized. - return (T)Convert.ChangeType(value, typeof(T)); - } + return DeserializeValue(value); } return @default; @@ -141,15 +134,7 @@ public T Read(string compositeKey, string key, T @default = default) object value = composite[key]; if (value != null) { - try - { - return Serializer.Deserialize((string)value); - } - catch - { - // Primitive types can't be deserialized. - return (T)Convert.ChangeType(value, typeof(T)); - } + return DeserializeValue(value); } } } @@ -167,17 +152,8 @@ public void Save(string key, T value) { InitCache(); - // Skip serialization for primitives. - if (typeof(T) == typeof(object) || Type.GetTypeCode(typeof(T)) != TypeCode.Object) - { - // Update the cache - Cache[key] = value; - } - else - { - // Update the cache - Cache[key] = Serializer.Serialize(value); - } + // Update the cache + Cache[key] = SerializeValue(value); if (AutoSync) { @@ -200,19 +176,24 @@ public void Save(string compositeKey, IDictionary values) { InitCache(); + var type = typeof(T); + var typeInfo = type.GetTypeInfo(); + if (KeyExists(compositeKey)) { ApplicationDataCompositeValue composite = (ApplicationDataCompositeValue)Cache[compositeKey]; foreach (KeyValuePair setting in values.ToList()) { + string key = setting.Key; + object value = SerializeValue(setting.Value); if (composite.ContainsKey(setting.Key)) { - composite[setting.Key] = Serializer.Serialize(setting.Value); + composite[key] = value; } else { - composite.Add(setting.Key, Serializer.Serialize(setting.Value)); + composite.Add(key, value); } } @@ -230,7 +211,9 @@ public void Save(string compositeKey, IDictionary values) ApplicationDataCompositeValue composite = new ApplicationDataCompositeValue(); foreach (KeyValuePair setting in values.ToList()) { - composite.Add(setting.Key, Serializer.Serialize(setting.Value)); + string key = setting.Key; + object value = SerializeValue(setting.Value); + composite.Add(key, value); } // Update the cache @@ -290,5 +273,42 @@ protected void DeleteCache() { Cache = null; } + + /// + /// Use the serializer to serialize a value appropriately for the type. + /// + /// + /// + /// + protected T DeserializeValue(object value) + { + try + { + return Serializer.Deserialize((string)value); + } + catch + { + // Primitive types can't be deserialized. + return (T)Convert.ChangeType(value, typeof(T)); + } + } + + private object SerializeValue(T value) + { + var type = typeof(T); + var typeInfo = type.GetTypeInfo(); + + // Skip serialization for primitives. + if (typeInfo.IsPrimitive || type == typeof(string)) + { + // Update the cache + return value; + } + else + { + // Update the cache + return Serializer.Serialize(value); + } + } } } From 5c00126cb2ccb4b52f99108f45b24eb5829a2553 Mon Sep 17 00:00:00 2001 From: Shane Weaver Date: Mon, 26 Apr 2021 15:01:26 -0700 Subject: [PATCH 2/3] Added comments --- .../BaseRoamingSettingsDataStore.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/BaseRoamingSettingsDataStore.cs b/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/BaseRoamingSettingsDataStore.cs index 28c77d9..137fb53 100644 --- a/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/BaseRoamingSettingsDataStore.cs +++ b/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/BaseRoamingSettingsDataStore.cs @@ -275,11 +275,11 @@ protected void DeleteCache() } /// - /// Use the serializer to serialize a value appropriately for the type. + /// Use the serializer to deserialize a value appropriately for the type. /// - /// - /// - /// + /// The type of object expected. + /// The value to deserialize. + /// An object of type T. protected T DeserializeValue(object value) { try @@ -293,7 +293,13 @@ protected T DeserializeValue(object value) } } - private object SerializeValue(T value) + /// + /// Use the serializer to serialize a value appropriately for the type. + /// + /// The type of object being serialized. + /// The object to serialize. + /// The serialized object. + protected object SerializeValue(T value) { var type = typeof(T); var typeInfo = type.GetTypeInfo(); From 7735dc6b77af32c1bb5432bf9325445120917c5b Mon Sep 17 00:00:00 2001 From: Shane Weaver Date: Wed, 28 Apr 2021 12:41:02 -0700 Subject: [PATCH 3/3] Updated serializer in OneDriveDataSource --- .../RoamingSettings/OneDriveDataSource.cs | 9 +++++---- .../RoamingSettings/OneDriveDataStore.cs | 20 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/OneDriveDataSource.cs b/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/OneDriveDataSource.cs index 8169388..c3ee0da 100644 --- a/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/OneDriveDataSource.cs +++ b/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/OneDriveDataSource.cs @@ -8,6 +8,7 @@ using CommunityToolkit.Net.Authentication; using CommunityToolkit.Net.Graph.Extensions; using Microsoft.Graph; +using Microsoft.Toolkit.Uwp.Helpers; namespace CommunityToolkit.Uwp.Graph.Helpers.RoamingSettings { @@ -34,9 +35,9 @@ internal static class OneDriveDataSource /// /// The type of object to save. /// A representing the asynchronous operation. - public static async Task Update(string userId, string fileWithExt, T fileContents) + public static async Task Update(string userId, string fileWithExt, T fileContents, IObjectSerializer serializer) { - var json = Graph.HttpProvider.Serializer.SerializeObject(fileContents); + var json = serializer.Serialize(fileContents) as string; using var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)); return await Graph.Users[userId].Drive.Special.AppRoot.ItemWithPath(fileWithExt).Content.Request().PutAsync(stream); @@ -47,13 +48,13 @@ public static async Task Update(string userId, string fileWithExt, /// /// The type of object to return. /// A representing the asynchronous operation. - public static async Task Retrieve(string userId, string fileWithExt) + public static async Task Retrieve(string userId, string fileWithExt, IObjectSerializer serializer) { Stream stream = await Graph.Users[userId].Drive.Special.AppRoot.ItemWithPath(fileWithExt).Content.Request().GetAsync(); string streamContents = new StreamReader(stream).ReadToEnd(); - return Graph.HttpProvider.Serializer.DeserializeObject(streamContents); + return serializer.Deserialize(streamContents); } /// diff --git a/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/OneDriveDataStore.cs b/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/OneDriveDataStore.cs index 46c433e..14f723a 100644 --- a/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/OneDriveDataStore.cs +++ b/CommunityToolkit.Uwp.Graph.Controls/Helpers/RoamingSettings/OneDriveDataStore.cs @@ -22,10 +22,11 @@ public class OneDriveDataStore : BaseRoamingSettingsDataStore /// The type of object to retrieve. /// The id of the target Graph user. /// The name of the file. + /// An object serializer for handling deserialization. /// The deserialized file contents. - public static async Task Get(string userId, string fileName) + public static async Task Get(string userId, string fileName, IObjectSerializer serializer) { - return await OneDriveDataSource.Retrieve(userId, fileName); + return await OneDriveDataSource.Retrieve(userId, fileName, serializer); } /// @@ -35,10 +36,11 @@ public static async Task Get(string userId, string fileName) /// The id of the target Graph user. /// The name of the file. /// The object to store. + /// An object serializer for handling serialization. /// A task. - public static async Task Set(string userId, string fileName, T fileContents) + public static async Task Set(string userId, string fileName, T fileContents, IObjectSerializer serializer) { - await OneDriveDataSource.Update(userId, fileName, fileContents); + await OneDriveDataSource.Update(userId, fileName, fileContents, serializer); } /// @@ -81,20 +83,20 @@ public override async Task Delete() /// public override async Task FileExistsAsync(string filePath) { - var roamingSettings = await Get(UserId, Id); + var roamingSettings = await Get(UserId, Id, Serializer); return roamingSettings != null; } /// public override async Task ReadFileAsync(string filePath, T @default = default) { - return await Get(UserId, filePath) ?? @default; + return await Get(UserId, filePath, Serializer) ?? @default; } /// public override async Task SaveFileAsync(string filePath, T value) { - await Set(UserId, filePath, value); + await Set(UserId, filePath, value, Serializer); // Can't convert DriveItem to StorageFile, so we return null instead. return null; @@ -110,7 +112,7 @@ public override async Task Sync() IDictionary remoteData = null; try { - remoteData = await Get>(UserId, fileName); + remoteData = await Get>(UserId, fileName, Serializer); } catch { @@ -145,7 +147,7 @@ public override async Task Sync() if (needsUpdate) { // Send updates for local values, overwriting the remote. - await Set(UserId, fileName, Cache); + await Set(UserId, fileName, Cache, Serializer); } SyncCompleted?.Invoke(this, new EventArgs());