Skip to content

Commit 025a0ae

Browse files
author
msftbot[bot]
authored
SystemSerializer update for BaseObjectStorageHelper (#3702)
## Fixes #3692 This introduces a new light-weight serializer which we can use within the toolkit for the `SystemInformation` class still. And then developers with more complex type needs can specify their own serializer for the `BaseObjectStorageHelper` classes. See the related issue for more details. Follow-on to #3637 and #3414 ## PR Type What kind of change does this PR introduce? <!-- Please uncomment one or more that apply to this PR. --> <!-- - Bugfix --> - Feature <!-- - Code style update (formatting) --> - Refactoring (no functional changes, no api changes) <!-- - Build or CI related changes --> <!-- - Documentation content changes --> <!-- - Sample app changes --> <!-- - Other... Please describe: --> ## What is the current behavior? Using `DataContractJsonSerializer`, though we had used `Newtonsoft.Json` in 6.1. ## What is the new behavior? Use new `SystemSerializer` which passes values to/from the Windows `ApplicationDataContainer` APIs directly. Updates our internal usages of this to the new system. Requires developer using the `BaseObjectStorageHelper` to provide a serializer implementation. This of course does provide a 'default'/system information within the toolkit now compared to our original thought of providing none at all before the `SystemInformation` problem was identified. ## PR Checklist Please check if your PR fulfills the following requirements: - [x] Tested code with current [supported SDKs](../readme.md#supported) - [ ] Pull Request has been submitted to the documentation repository [instructions](..\contributing.md#docs). Link: <!-- docs PR link --> - [ ] Sample in sample app has been added / updated (for bug fixes / features) - [ ] Icon has been created (if new sample) following the [Thumbnail Style Guide and templates](https://github.com/windows-toolkit/WindowsCommunityToolkit-design-assets) - [ ] New major technical changes in the toolkit have or will be added to the [Wiki](https://github.com/windows-toolkit/WindowsCommunityToolkit/wiki) e.g. build changes, source generators, testing infrastructure, sample creation changes, etc... - [ ] Tests for the changes have been added (for bug fixes / features) (if applicable) - [ ] Header has been added to all new source files (run *build/UpdateHeaders.bat*) - [ ] Contains **NO** breaking changes <!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. Please note that breaking changes are likely to be rejected within minor release cycles or held until major versions. --> ## Other information I tested copying the system.dat file from the Settings folder of our 6.1 sample app to the development version with the changes, no issues with `SystemInformation` reading the old data. Updated/added unit tests to test the old json layer vs. reading from the new SystemSerializer as well as just testing a new `System.Text.Json` complex scenario. Added tests for exceptions. TODO: - [ ] Add more tests? - [x] Run XAML Islands SystemInformation test - [ ] Do we want `SystemSerializer` to handle a few more 'basic' (but non-primitive) types? E.g. @Sergio0694 has a [similar implementation for a different related system](https://github.com/Sergio0694/Brainf_ckSharp/blob/master/src/Brainf_ckSharp.Services.Uwp/SettingsService.cs) - [ ] ???
2 parents f41314e + 8dc6abb commit 025a0ae

File tree

17 files changed

+246
-147
lines changed

17 files changed

+246
-147
lines changed

GazeInputTest/GazeInputTest.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<DefaultLanguage>en-US</DefaultLanguage>
1313
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
1414
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.19041.0</TargetPlatformVersion>
15-
<TargetPlatformMinVersion>10.0.17134.0</TargetPlatformMinVersion>
15+
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
1616
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
1717
<FileAlignment>512</FileAlignment>
1818
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

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: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,13 @@ public abstract class BaseObjectStorageHelper : IObjectStorageHelper
2121
/// <summary>
2222
/// Initializes a new instance of the <see cref="BaseObjectStorageHelper"/> class,
2323
/// which can read and write data using the provided <see cref="IObjectSerializer"/>;
24-
/// if none is provided, a default Json serializer will be used (based on <see cref="DataContractSerializer"/>).
25-
/// In 6.1 and older the default Serializer was based on Newtonsoft.Json and the new default Serializer may behave differently.
24+
/// In 6.1 and older the default Serializer was based on Newtonsoft.Json.
2625
/// To implement a <see cref="IObjectSerializer"/> based on Newtonsoft.Json or System.Text.Json see https://aka.ms/wct/storagehelper-migration
2726
/// </summary>
2827
/// <param name="objectSerializer">The serializer to use.</param>
29-
public BaseObjectStorageHelper(IObjectSerializer objectSerializer = null)
28+
public BaseObjectStorageHelper(IObjectSerializer objectSerializer)
3029
{
31-
serializer = objectSerializer ?? new JsonObjectSerializer();
30+
serializer = objectSerializer ?? throw new ArgumentNullException(nameof(objectSerializer));
3231
}
3332

3433
/// <summary>
@@ -85,15 +84,7 @@ public bool KeyExists(string compositeKey, string key)
8584
return @default;
8685
}
8786

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

9990
/// <summary>
@@ -132,14 +123,7 @@ public void Save<T>(string key, T value)
132123
var type = typeof(T);
133124
var typeInfo = type.GetTypeInfo();
134125

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

145129
/// <summary>
@@ -214,7 +198,7 @@ public Task<bool> FileExistsAsync(string filePath)
214198
/// <returns>The <see cref="StorageFile"/> where the object was saved</returns>
215199
public Task<StorageFile> SaveFileAsync<T>(string filePath, T value)
216200
{
217-
return StorageFileHelper.WriteTextToFileAsync(Folder, serializer.Serialize(value), filePath, CreationCollisionOption.ReplaceExisting);
201+
return StorageFileHelper.WriteTextToFileAsync(Folder, serializer.Serialize(value)?.ToString(), filePath, CreationCollisionOption.ReplaceExisting);
218202
}
219203
}
220204
}

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/JsonObjectSerializer.cs

Lines changed: 0 additions & 29 deletions
This file was deleted.

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ public class LocalObjectStorageHelper : BaseObjectStorageHelper
1515
/// <summary>
1616
/// Initializes a new instance of the <see cref="LocalObjectStorageHelper"/> class,
1717
/// which can read and write data using the provided <see cref="IObjectSerializer"/>;
18-
/// if none is provided, a default Json serializer will be used (based on <see cref="DataContractSerializer"/>).
19-
/// In 6.1 and older the default Serializer was based on Newtonsoft.Json and the new default Serializer may behave differently.
20-
/// To implement a <see cref="IObjectSerializer"/> based on Newtonsoft.Json or System.Text.Json see https://aka.ms/wct/storagehelper-migration
18+
/// In 6.1 and older the default Serializer was based on Newtonsoft.Json.
19+
/// To implement an <see cref="IObjectSerializer"/> based on System.Text.Json, Newtonsoft.Json, or DataContractJsonSerializer see https://aka.ms/wct/storagehelper-migration
2120
/// </summary>
2221
/// <param name="objectSerializer">The serializer to use.</param>
23-
public LocalObjectStorageHelper(IObjectSerializer objectSerializer = null)
22+
public LocalObjectStorageHelper(IObjectSerializer objectSerializer)
2423
: base(objectSerializer)
2524
{
2625
Settings = ApplicationData.Current.LocalSettings;

0 commit comments

Comments
 (0)