Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -109,15 +110,7 @@ public T Read<T>(string key, T @default = default)
{
if (Cache != null && Cache.TryGetValue(key, out object value))
{
try
{
return Serializer.Deserialize<T>((string)value);
}
catch
{
// Primitive types can't be deserialized.
return (T)Convert.ChangeType(value, typeof(T));
}
return DeserializeValue<T>(value);
}

return @default;
Expand All @@ -141,15 +134,7 @@ public T Read<T>(string compositeKey, string key, T @default = default)
object value = composite[key];
if (value != null)
{
try
{
return Serializer.Deserialize<T>((string)value);
}
catch
{
// Primitive types can't be deserialized.
return (T)Convert.ChangeType(value, typeof(T));
}
return DeserializeValue<T>(value);
}
}
}
Expand All @@ -167,17 +152,8 @@ public void Save<T>(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)
{
Expand All @@ -200,19 +176,24 @@ public void Save<T>(string compositeKey, IDictionary<string, T> values)
{
InitCache();

var type = typeof(T);
var typeInfo = type.GetTypeInfo();

if (KeyExists(compositeKey))
{
ApplicationDataCompositeValue composite = (ApplicationDataCompositeValue)Cache[compositeKey];

foreach (KeyValuePair<string, T> 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);
}
}

Expand All @@ -230,7 +211,9 @@ public void Save<T>(string compositeKey, IDictionary<string, T> values)
ApplicationDataCompositeValue composite = new ApplicationDataCompositeValue();
foreach (KeyValuePair<string, T> 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
Expand Down Expand Up @@ -290,5 +273,48 @@ protected void DeleteCache()
{
Cache = null;
}

/// <summary>
/// Use the serializer to deserialize a value appropriately for the type.
/// </summary>
/// <typeparam name="T">The type of object expected.</typeparam>
/// <param name="value">The value to deserialize.</param>
/// <returns>An object of type T.</returns>
protected T DeserializeValue<T>(object value)
{
try
{
return Serializer.Deserialize<T>((string)value);
}
catch
{
// Primitive types can't be deserialized.
return (T)Convert.ChangeType(value, typeof(T));
}
}

/// <summary>
/// Use the serializer to serialize a value appropriately for the type.
/// </summary>
/// <typeparam name="T">The type of object being serialized.</typeparam>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized object.</returns>
protected object SerializeValue<T>(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);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -34,9 +35,9 @@ internal static class OneDriveDataSource
/// </summary>
/// <typeparam name="T">The type of object to save.</typeparam>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static async Task<DriveItem> Update<T>(string userId, string fileWithExt, T fileContents)
public static async Task<DriveItem> Update<T>(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<DriveItem>(stream);
Expand All @@ -47,13 +48,13 @@ public static async Task<DriveItem> Update<T>(string userId, string fileWithExt,
/// </summary>
/// <typeparam name="T">The type of object to return.</typeparam>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static async Task<T> Retrieve<T>(string userId, string fileWithExt)
public static async Task<T> Retrieve<T>(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<T>(streamContents);
return serializer.Deserialize<T>(streamContents);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ public class OneDriveDataStore : BaseRoamingSettingsDataStore
/// <typeparam name="T">The type of object to retrieve.</typeparam>
/// <param name="userId">The id of the target Graph user.</param>
/// <param name="fileName">The name of the file.</param>
/// <param name="serializer">An object serializer for handling deserialization.</param>
/// <returns>The deserialized file contents.</returns>
public static async Task<T> Get<T>(string userId, string fileName)
public static async Task<T> Get<T>(string userId, string fileName, IObjectSerializer serializer)
{
return await OneDriveDataSource.Retrieve<T>(userId, fileName);
return await OneDriveDataSource.Retrieve<T>(userId, fileName, serializer);
}

/// <summary>
Expand All @@ -35,10 +36,11 @@ public static async Task<T> Get<T>(string userId, string fileName)
/// <param name="userId">The id of the target Graph user.</param>
/// <param name="fileName">The name of the file.</param>
/// <param name="fileContents">The object to store.</param>
/// <param name="serializer">An object serializer for handling serialization.</param>
/// <returns>A task.</returns>
public static async Task Set<T>(string userId, string fileName, T fileContents)
public static async Task Set<T>(string userId, string fileName, T fileContents, IObjectSerializer serializer)
{
await OneDriveDataSource.Update<T>(userId, fileName, fileContents);
await OneDriveDataSource.Update(userId, fileName, fileContents, serializer);
}

/// <summary>
Expand Down Expand Up @@ -81,20 +83,20 @@ public override async Task Delete()
/// <inheritdoc />
public override async Task<bool> FileExistsAsync(string filePath)
{
var roamingSettings = await Get<object>(UserId, Id);
var roamingSettings = await Get<object>(UserId, Id, Serializer);
return roamingSettings != null;
}

/// <inheritdoc />
public override async Task<T> ReadFileAsync<T>(string filePath, T @default = default)
{
return await Get<T>(UserId, filePath) ?? @default;
return await Get<T>(UserId, filePath, Serializer) ?? @default;
}

/// <inheritdoc />
public override async Task<StorageFile> SaveFileAsync<T>(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;
Expand All @@ -110,7 +112,7 @@ public override async Task Sync()
IDictionary<string, object> remoteData = null;
try
{
remoteData = await Get<IDictionary<string, object>>(UserId, fileName);
remoteData = await Get<IDictionary<string, object>>(UserId, fileName, Serializer);
}
catch
{
Expand Down Expand Up @@ -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());
Expand Down