Skip to content

Commit b664b23

Browse files
Created a SystemSerializer to handle our primitive types within SystemInformation
Tested copying data from 6.1 Sample App and was able to read/resume file writes with this new serializer. TODO: Update tests.
1 parent 6b901d8 commit b664b23

File tree

11 files changed

+96
-74
lines changed

11 files changed

+96
-74
lines changed

Microsoft.Toolkit.Uwp.SampleApp/Controls/SampleAppMarkdownRenderer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ public string DesiredLang
416416
/// <summary>
417417
/// The Local Storage Helper.
418418
/// </summary>
419-
private LocalObjectStorageHelper storage = new LocalObjectStorageHelper();
419+
private LocalObjectStorageHelper storage = new LocalObjectStorageHelper(new SystemSerializer());
420420

421421
/// <summary>
422422
/// DocFX note types and styling info, keyed by identifier.

Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class Sample
3939

4040
public static async void EnsureCacheLatest()
4141
{
42-
var settingsStorage = new LocalObjectStorageHelper();
42+
var settingsStorage = new LocalObjectStorageHelper(new SystemSerializer());
4343

4444
var onlineDocsSHA = await GetDocsSHA();
4545
var cacheSHA = settingsStorage.Read<string>(_cacheSHAKey);

Microsoft.Toolkit.Uwp.SampleApp/Models/Samples.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public static class Samples
2121
private static SemaphoreSlim _semaphore = new SemaphoreSlim(1);
2222

2323
private static LinkedList<Sample> _recentSamples;
24-
private static RoamingObjectStorageHelper _roamingObjectStorageHelper = new RoamingObjectStorageHelper();
24+
private static LocalObjectStorageHelper _localObjectStorageHelper = new LocalObjectStorageHelper(new SystemSerializer());
2525

2626
public static async Task<SampleCategory> GetCategoryBySample(Sample sample)
2727
{
@@ -98,7 +98,7 @@ public static async Task<LinkedList<Sample>> GetRecentSamples()
9898
if (_recentSamples == null)
9999
{
100100
_recentSamples = new LinkedList<Sample>();
101-
var savedSamples = _roamingObjectStorageHelper.Read<string>(_recentSamplesStorageKey);
101+
var savedSamples = _localObjectStorageHelper.Read<string>(_recentSamplesStorageKey);
102102

103103
if (savedSamples != null)
104104
{
@@ -144,7 +144,7 @@ private static void SaveRecentSamples()
144144
}
145145

146146
var str = string.Join(";", _recentSamples.Take(10).Select(s => s.Name).ToArray());
147-
_roamingObjectStorageHelper.Save<string>(_recentSamplesStorageKey, str);
147+
_localObjectStorageHelper.Save<string>(_recentSamplesStorageKey, str);
148148
}
149149
}
150150
}

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Object Storage/ObjectStoragePage.xaml

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,33 @@
1-
<Page
2-
x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.ObjectStoragePage"
3-
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4-
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5-
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6-
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7-
mc:Ignorable="d">
1+
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.ObjectStoragePage"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6+
mc:Ignorable="d">
87

98
<ScrollViewer>
109
<StackPanel Margin="20">
11-
<ToggleSwitch x:Name="StorageModeToggle" HorizontalAlignment="Center"
12-
OnContent="Roaming storage (save across all your devices)"
13-
OffContent="Local storage (save on this device only)" />
10+
<TextBox x:Name="KeyTextBox"
11+
Margin="0,10,0,0"
12+
PlaceholderText="Key" />
1413

15-
<TextBox x:Name="KeyTextBox" PlaceholderText="Key" Margin="0 10 0 0" />
14+
<TextBox x:Name="ContentTextBox"
15+
Margin="0,10,0,0"
16+
PlaceholderText="Content to save" />
1617

17-
<TextBox x:Name="ContentTextBox" PlaceholderText="Content to save" Margin="0 10 0 0" />
18-
19-
<StackPanel Margin="0 10 0 0" Orientation="Horizontal" HorizontalAlignment="Center">
20-
<Button x:Name="ReadButton" Content="Read from key" HorizontalAlignment="Center" Margin="5 0"
21-
Click="ReadButton_Click" />
22-
<Button x:Name="SaveButton" Content="Save" HorizontalAlignment="Center" Margin="5 0"
23-
Click="SaveButton_Click" />
18+
<StackPanel Margin="0,10,0,0"
19+
HorizontalAlignment="Center"
20+
Orientation="Horizontal">
21+
<Button x:Name="ReadButton"
22+
Margin="5,0"
23+
HorizontalAlignment="Center"
24+
Click="ReadButton_Click"
25+
Content="Read from key" />
26+
<Button x:Name="SaveButton"
27+
Margin="5,0"
28+
HorizontalAlignment="Center"
29+
Click="SaveButton_Click"
30+
Content="Save" />
2431
</StackPanel>
2532
</StackPanel>
2633
</ScrollViewer>

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Object Storage/ObjectStoragePage.xaml.cs

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
99
{
1010
public sealed partial class ObjectStoragePage
1111
{
12-
private readonly IObjectStorageHelper localStorageHelper = new LocalObjectStorageHelper();
13-
private readonly IObjectStorageHelper roamingStorageHelper = new RoamingObjectStorageHelper();
12+
private readonly IObjectStorageHelper localStorageHelper = new LocalObjectStorageHelper(new SystemSerializer());
1413

1514
public ObjectStoragePage()
1615
{
@@ -24,21 +23,10 @@ private void ReadButton_Click(object sender, RoutedEventArgs e)
2423
return;
2524
}
2625

27-
if (StorageModeToggle.IsOn)
26+
// Read from local storage
27+
if (localStorageHelper.KeyExists(KeyTextBox.Text))
2828
{
29-
// Read from roaming storage
30-
if (roamingStorageHelper.KeyExists(KeyTextBox.Text))
31-
{
32-
ContentTextBox.Text = roamingStorageHelper.Read<string>(KeyTextBox.Text);
33-
}
34-
}
35-
else
36-
{
37-
// Read from local storage
38-
if (localStorageHelper.KeyExists(KeyTextBox.Text))
39-
{
40-
ContentTextBox.Text = localStorageHelper.Read<string>(KeyTextBox.Text);
41-
}
29+
ContentTextBox.Text = localStorageHelper.Read<string>(KeyTextBox.Text);
4230
}
4331
}
4432

@@ -54,16 +42,8 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
5442
return;
5543
}
5644

57-
if (StorageModeToggle.IsOn)
58-
{
59-
// Save into roaming storage
60-
roamingStorageHelper.Save(KeyTextBox.Text, ContentTextBox.Text);
61-
}
62-
else
63-
{
64-
// Save into local storage
65-
localStorageHelper.Save(KeyTextBox.Text, ContentTextBox.Text);
66-
}
45+
// Save into local storage
46+
localStorageHelper.Save(KeyTextBox.Text, ContentTextBox.Text);
6747
}
6848
}
6949
}

Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/BaseObjectStorageHelper.cs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,7 @@ public bool KeyExists(string compositeKey, string key)
8484
return @default;
8585
}
8686

87-
var type = typeof(T);
88-
var typeInfo = type.GetTypeInfo();
89-
90-
if (typeInfo.IsPrimitive || type == typeof(string))
91-
{
92-
return (T)Convert.ChangeType(value, type);
93-
}
94-
95-
return serializer.Deserialize<T>((string)value);
87+
return serializer.Deserialize<T>(value);
9688
}
9789

9890
/// <summary>
@@ -131,14 +123,7 @@ public void Save<T>(string key, T value)
131123
var type = typeof(T);
132124
var typeInfo = type.GetTypeInfo();
133125

134-
if (typeInfo.IsPrimitive || type == typeof(string))
135-
{
136-
Settings.Values[key] = value;
137-
}
138-
else
139-
{
140-
Settings.Values[key] = serializer.Serialize(value);
141-
}
126+
Settings.Values[key] = serializer.Serialize(value);
142127
}
143128

144129
/// <summary>
@@ -213,7 +198,7 @@ public Task<bool> FileExistsAsync(string filePath)
213198
/// <returns>The <see cref="StorageFile"/> where the object was saved</returns>
214199
public Task<StorageFile> SaveFileAsync<T>(string filePath, T value)
215200
{
216-
return StorageFileHelper.WriteTextToFileAsync(Folder, serializer.Serialize(value), filePath, CreationCollisionOption.ReplaceExisting);
201+
return StorageFileHelper.WriteTextToFileAsync(Folder, serializer.Serialize(value)?.ToString(), filePath, CreationCollisionOption.ReplaceExisting);
217202
}
218203
}
219204
}

Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/IObjectSerializer.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ namespace Microsoft.Toolkit.Uwp.Helpers
1010
public interface IObjectSerializer
1111
{
1212
/// <summary>
13-
/// Serialize an object into a string.
13+
/// Serialize an object into a string. It is recommended to use strings as the final format for objects if you plan to use the <see cref="BaseObjectStorageHelper.SaveFileAsync{T}(string, T)"/> method.
1414
/// </summary>
1515
/// <typeparam name="T">The type of the object to serialize.</typeparam>
1616
/// <param name="value">The object to serialize.</param>
1717
/// <returns>The serialized object.</returns>
18-
string Serialize<T>(T value);
18+
object Serialize<T>(T value);
1919

2020
/// <summary>
21-
/// Deserialize a string into an object.
21+
/// Deserialize a primitive or string into an object of the given type.
2222
/// </summary>
2323
/// <typeparam name="T">The type of the deserialized object.</typeparam>
2424
/// <param name="value">The string to deserialize.</param>
2525
/// <returns>The deserialized object.</returns>
26-
T Deserialize<T>(string value);
26+
T Deserialize<T>(object value);
2727
}
2828
}

Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/LocalObjectStorageHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class LocalObjectStorageHelper : BaseObjectStorageHelper
1616
/// Initializes a new instance of the <see cref="LocalObjectStorageHelper"/> class,
1717
/// which can read and write data using the provided <see cref="IObjectSerializer"/>;
1818
/// In 6.1 and older the default Serializer was based on Newtonsoft.Json.
19-
/// To implement a <see cref="IObjectSerializer"/> based on Newtonsoft.Json or System.Text.Json see https://aka.ms/wct/storagehelper-migration
19+
/// To implement an <see cref="IObjectSerializer"/> based on System.Text.Json, Newtonsoft.Json, or DataContractJsonSerializer see https://aka.ms/wct/storagehelper-migration
2020
/// </summary>
2121
/// <param name="objectSerializer">The serializer to use.</param>
2222
public LocalObjectStorageHelper(IObjectSerializer objectSerializer)

Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/RoamingObjectStorageHelper.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System;
56
using System.Runtime.Serialization;
67
using Windows.Storage;
78

@@ -10,13 +11,14 @@ namespace Microsoft.Toolkit.Uwp.Helpers
1011
/// <summary>
1112
/// Store data in the Roaming environment (shared across all user devices).
1213
/// </summary>
14+
[Obsolete("Package State Roaming will be removed in a futures Windows Update, see https://docs.microsoft.com/windows/deployment/planning/windows-10-deprecated-features for more information.")]
1315
public class RoamingObjectStorageHelper : BaseObjectStorageHelper
1416
{
1517
/// <summary>
1618
/// Initializes a new instance of the <see cref="RoamingObjectStorageHelper"/> class,
1719
/// which can read and write data using the provided <see cref="IObjectSerializer"/>;
1820
/// In 6.1 and older the default Serializer was based on Newtonsoft.Json.
19-
/// To implement a <see cref="IObjectSerializer"/> based on Newtonsoft.Json or System.Text.Json see https://aka.ms/wct/storagehelper-migration
21+
/// To implement an <see cref="IObjectSerializer"/> based on System.Text.Json, Newtonsoft.Json, or DataContractJsonSerializer see https://aka.ms/wct/storagehelper-migration
2022
/// </summary>
2123
/// <param name="objectSerializer">The serializer to use.</param>
2224
public RoamingObjectStorageHelper(IObjectSerializer objectSerializer)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Reflection;
7+
using Microsoft.Toolkit.Diagnostics;
8+
using Windows.Storage;
9+
10+
namespace Microsoft.Toolkit.Uwp.Helpers
11+
{
12+
/// <summary>
13+
/// A bare-bones serializer which knows how to deal with primitive types and strings only. It will store them directly based on the <see cref="ApplicationDataContainer"/> API.
14+
/// It is recommended for more complex scenarios to implement your own <see cref="IObjectSerializer"/> based on System.Text.Json, Newtonsoft.Json, or DataContractJsonSerializer see https://aka.ms/wct/storagehelper-migration
15+
/// </summary>
16+
public class SystemSerializer : IObjectSerializer
17+
{
18+
/// <summary>
19+
/// Take a primitive value from storage and return it as the requested type using the <see cref="Convert.ChangeType(object, Type)"/> API.
20+
/// </summary>
21+
/// <typeparam name="T">Type to convert value to.</typeparam>
22+
/// <param name="value">Value from storage to convert.</param>
23+
/// <returns>Deserialized value or default value.</returns>
24+
public T Deserialize<T>(object value)
25+
{
26+
var type = typeof(T);
27+
var typeInfo = type.GetTypeInfo();
28+
29+
if (typeInfo.IsPrimitive || type == typeof(string))
30+
{
31+
return (T)Convert.ChangeType(value, type);
32+
}
33+
34+
return ThrowHelper.ThrowNotSupportedException<T>("This serializer can only handle primitive types and strings. Please implement your own IObjectSerializer for more complex scenarios.");
35+
}
36+
37+
/// <summary>
38+
/// Returns the value so that it can be serialized by the <see cref="ApplicationDataContainer"/> API directly.
39+
/// </summary>
40+
/// <typeparam name="T">Type to serialize from.</typeparam>
41+
/// <param name="value">Value to serialize.</param>
42+
/// <returns>String representation of value.</returns>
43+
public object Serialize<T>(T value)
44+
{
45+
return value;
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)