diff --git a/Directory.Build.props b/Directory.Build.props
index 28acef2..8f1e9e9 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,8 +2,8 @@
- 3.1.14
- 5.0.5
+ 6.0.12
+ 7.0.1
\ No newline at end of file
diff --git a/README.md b/README.md
index 703cebf..3d1e274 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ builder.Services.AddBlazoredSessionStorage(config => {
```
### SetItem[Async] method now serializes string values
-Prior to v2 we bypassed the serialization of string values as it seemed a pointless as string can be stored directly. However, this led to some edge cases where nullable strings were being saved as the string `"null"`. Then when retrieved, instead of being null the value was `"null"`. By serializing strings this issue is taken care of.
+Prior to v2 we bypassed the serialization of string values as it seemed pointless as string can be stored directly. However, this led to some edge cases where nullable strings were being saved as the string `"null"`. Then when retrieved, instead of being null the value was `"null"`. By serializing strings this issue is taken care of.
For those who wish to save raw string values, a new method `SetValueAsString[Async]` is available. This will save a string value without attempting to serialize it and will throw an exception if a null string is attempted to be saved.
## Installing
@@ -42,7 +42,7 @@ You can also install via the .NET CLI with the following command:
dotnet add package Blazored.SessionStorage
```
-If you're using Visual Studio you can also install via the built in NuGet package manager.
+If you're using Jetbrains Rider or Visual Studio you can also install via the built in NuGet package manager.
## Setup
@@ -69,6 +69,17 @@ public static async Task Main(string[] args)
}
```
+### Registering services as Singleton - Blazor WebAssembly **ONLY**
+99% of developers will want to register Blazored SessionStorage using the method described above. However, in some very specific scenarios,
+developers may have a need to register services as Singleton as apposed to Scoped. This is possible by using the following method:
+
+```csharp
+builder.Services.AddBlazoredSessionStorageAsSingleton();
+```
+
+**This method will not work with Blazor Server applications as Blazor's JS interop services are registered as Scoped and cannot be injected into Singletons.**
+
+
## Usage (Blazor WebAssembly)
To use Blazored.SessionStorage in Blazor WebAssembly, inject the `ISessionStorageService` per the example below.
@@ -128,9 +139,11 @@ The APIs available are:
- GetItemAsync()
- GetItemAsStringAsync()
- RemoveItemAsync()
+ - RemoveItemsAsync()
- ClearAsync()
- LengthAsync()
- KeyAsync()
+ - KeysAsync()
- ContainKeyAsync()
- synchronous via `ISyncSessionStorageService` (Synchronous methods are **only** available in Blazor WebAssembly):
@@ -139,9 +152,11 @@ The APIs available are:
- GetItem()
- GetItemAsString()
- RemoveItem()
+ - RemovesItem()
- Clear()
- Length()
- Key()
+ - Keys()
- ContainKey()
**Note:** Blazored.SessionStorage methods will handle the serialisation and de-serialisation of the data for you, the exception is the `GetItemAsString[Async]` method which will return the raw string value from session storage.
@@ -178,6 +193,24 @@ You can find an example of this in the Blazor Server sample project. The standar
## Testing with bUnit
This library provides test extensions for use with the [bUnit testing library](https://bunit.dev/). Using these test extensions will provide an in memory implementation which mimics session storage allowing more realistic testing of your components.
+### Installing
+
+To install the package add the following line to you csproj file replacing x.x.x with the latest version number (found at the top of this file):
+
+```
+
+```
+
+You can also install via the .NET CLI with the following command:
+
+```
+dotnet add package Blazored.SessionStorage.TestExtensions
+```
+
+If you're using Jetbrains Rider or Visual Studio you can also install via the built in NuGet package manager.
+
+### Usage example
+
Below is an example test which uses these extensions. You can find an example project which shows this code in action in the samples folder.
```c#
diff --git a/src/Blazored.SessionStorage.TestExtensions/Blazored.SessionStorage.TestExtensions.csproj b/src/Blazored.SessionStorage.TestExtensions/Blazored.SessionStorage.TestExtensions.csproj
index f75b71b..40800be 100644
--- a/src/Blazored.SessionStorage.TestExtensions/Blazored.SessionStorage.TestExtensions.csproj
+++ b/src/Blazored.SessionStorage.TestExtensions/Blazored.SessionStorage.TestExtensions.csproj
@@ -1,7 +1,7 @@
- netstandard2.1;net7.0
+ net6.0;net7.0Chris Sainty
@@ -26,12 +26,16 @@
Blazored.SessionStorage.snk
+
+
+
+
-
+
diff --git a/src/Blazored.SessionStorage.TestExtensions/InMemoryStorageProvider.cs b/src/Blazored.SessionStorage.TestExtensions/InMemoryStorageProvider.cs
index 268d1e3..36615c0 100644
--- a/src/Blazored.SessionStorage.TestExtensions/InMemoryStorageProvider.cs
+++ b/src/Blazored.SessionStorage.TestExtensions/InMemoryStorageProvider.cs
@@ -7,12 +7,12 @@ namespace Blazored.SessionStorage.TestExtensions
{
internal class InMemoryStorageProvider : IStorageProvider
{
- private readonly Dictionary _dataStore = new Dictionary();
+ private readonly Dictionary _dataStore = new();
public void Clear()
=> _dataStore.Clear();
- public ValueTask ClearAsync(CancellationToken? cancellationToken = null)
+ public ValueTask ClearAsync(CancellationToken cancellationToken = default)
{
_dataStore.Clear();
return new ValueTask(Task.CompletedTask);
@@ -21,35 +21,56 @@ public ValueTask ClearAsync(CancellationToken? cancellationToken = null)
public bool ContainKey(string key)
=> _dataStore.ContainsKey(key);
- public ValueTask ContainKeyAsync(string key, CancellationToken? cancellationToken = null)
- => new ValueTask(ContainKey(key));
+ public ValueTask ContainKeyAsync(string key, CancellationToken cancellationToken = default)
+ => new(ContainKey(key));
public string GetItem(string key)
- => _dataStore.ContainsKey(key) ? _dataStore[key] : default;
+ => _dataStore.TryGetValue(key, out var value) ? value : default;
- public ValueTask GetItemAsync(string key, CancellationToken? cancellationToken = null)
- => new ValueTask(GetItem(key));
+ public ValueTask GetItemAsync(string key, CancellationToken cancellationToken = default)
+ => new(GetItem(key));
public string Key(int index)
=> index > _dataStore.Count - 1 ? default : _dataStore.ElementAt(index).Key;
- public ValueTask KeyAsync(int index, CancellationToken? cancellationToken = null)
- => new ValueTask(Key(index));
+ public IEnumerable Keys()
+ => _dataStore.Keys.ToList();
+
+ public ValueTask KeyAsync(int index, CancellationToken cancellationToken = default)
+ => new(Key(index));
+
+ public ValueTask> KeysAsync(CancellationToken cancellationToken = default)
+ => new(_dataStore.Keys.ToList());
public int Length()
=> _dataStore.Count;
- public ValueTask LengthAsync(CancellationToken? cancellationToken = null)
- => new ValueTask(Length());
+ public ValueTask LengthAsync(CancellationToken cancellationToken = default)
+ => new(Length());
public void RemoveItem(string key)
=> _dataStore.Remove(key);
- public ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null)
+ public ValueTask RemoveItemAsync(string key, CancellationToken cancellationToken = default)
{
RemoveItem(key);
return new ValueTask(Task.CompletedTask);
}
+
+ public void RemoveItems(IEnumerable keys)
+ {
+ foreach (var key in keys)
+ {
+ _dataStore.Remove(key);
+ }
+ }
+
+ public ValueTask RemoveItemsAsync(IEnumerable keys, CancellationToken cancellationToken = default)
+ {
+ RemoveItems(keys);
+
+ return new ValueTask(Task.CompletedTask);
+ }
public void SetItem(string key, string data)
{
@@ -63,7 +84,7 @@ public void SetItem(string key, string data)
}
}
- public ValueTask SetItemAsync(string key, string data, CancellationToken? cancellationToken = null)
+ public ValueTask SetItemAsync(string key, string data, CancellationToken cancellationToken = default)
{
SetItem(key, data);
return new ValueTask(Task.CompletedTask);
diff --git a/src/Blazored.SessionStorage/Blazored.SessionStorage.csproj b/src/Blazored.SessionStorage/Blazored.SessionStorage.csproj
index 2ff8b60..07ebd5d 100644
--- a/src/Blazored.SessionStorage/Blazored.SessionStorage.csproj
+++ b/src/Blazored.SessionStorage/Blazored.SessionStorage.csproj
@@ -1,7 +1,7 @@
- netstandard2.1;net7.0
+ net6.0;net7.0Chris Sainty
@@ -26,20 +26,16 @@
Blazored.SessionStorage.snk
-
- 3.0
-
-
-
+
-
-
+
+
-
+
-
+
@@ -62,4 +58,4 @@
-
+
\ No newline at end of file
diff --git a/src/Blazored.SessionStorage/BrowserStorageProvider.cs b/src/Blazored.SessionStorage/BrowserStorageProvider.cs
index 6c1e398..883c4bb 100644
--- a/src/Blazored.SessionStorage/BrowserStorageProvider.cs
+++ b/src/Blazored.SessionStorage/BrowserStorageProvider.cs
@@ -1,88 +1,352 @@
using Microsoft.JSInterop;
using System;
+using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using Blazored.SessionStorage.Exceptions;
-namespace Blazored.SessionStorage
+namespace Blazored.SessionStorage;
+
+internal class BrowserStorageProvider : IStorageProvider
{
- internal class BrowserStorageProvider : IStorageProvider
+ private const string StorageNotAvailableMessage = "Unable to access the browser storage. This is most likely due to the browser settings.";
+
+ private readonly IJSRuntime _jSRuntime;
+ private readonly IJSInProcessRuntime _jSInProcessRuntime;
+
+ public BrowserStorageProvider(IJSRuntime jSRuntime)
+ {
+ _jSRuntime = jSRuntime;
+ _jSInProcessRuntime = jSRuntime as IJSInProcessRuntime;
+ }
+
+ public async ValueTask ClearAsync(CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ await _jSRuntime.InvokeVoidAsync("sessionStorage.clear", cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
+
+ throw;
+ }
+ }
+
+ public async ValueTask GetItemAsync(string key, CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ return await _jSRuntime.InvokeAsync("sessionStorage.getItem", cancellationToken, key);
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
+
+ throw;
+ }
+ }
+
+ public async ValueTask KeyAsync(int index, CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ return await _jSRuntime.InvokeAsync("sessionStorage.key", cancellationToken, index);
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
+
+ throw;
+ }
+ }
+
+ public async ValueTask> KeysAsync(CancellationToken cancellationToken = default)
{
- private readonly IJSRuntime _jSRuntime;
- private readonly IJSInProcessRuntime _jSInProcessRuntime;
+ try
+ {
+ return await _jSRuntime.InvokeAsync>("eval", cancellationToken, "Object.keys(sessionStorage)");
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
+
+ throw;
+ }
+ }
- public BrowserStorageProvider(IJSRuntime jSRuntime)
+ public async ValueTask ContainKeyAsync(string key, CancellationToken cancellationToken = default)
+ {
+ try
{
- _jSRuntime = jSRuntime;
- _jSInProcessRuntime = jSRuntime as IJSInProcessRuntime;
+ return await _jSRuntime.InvokeAsync("sessionStorage.hasOwnProperty", cancellationToken, key);
}
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
- public ValueTask ClearAsync(CancellationToken? cancellationToken = null)
- => _jSRuntime.InvokeVoidAsync("sessionStorage.clear", cancellationToken ?? CancellationToken.None);
+ throw;
+ }
+ }
- public ValueTask GetItemAsync(string key, CancellationToken? cancellationToken = null)
- => _jSRuntime.InvokeAsync("sessionStorage.getItem", cancellationToken ?? CancellationToken.None, key);
+ public async ValueTask LengthAsync(CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ return await _jSRuntime.InvokeAsync("eval", cancellationToken, "sessionStorage.length");
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
- public ValueTask KeyAsync(int index, CancellationToken? cancellationToken = null)
- => _jSRuntime.InvokeAsync("sessionStorage.key", cancellationToken ?? CancellationToken.None, index);
+ throw;
+ }
+ }
- public ValueTask ContainKeyAsync(string key, CancellationToken? cancellationToken = null)
- => _jSRuntime.InvokeAsync("sessionStorage.hasOwnProperty", cancellationToken ?? CancellationToken.None, key);
+ public async ValueTask RemoveItemAsync(string key, CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ await _jSRuntime.InvokeVoidAsync("sessionStorage.removeItem", cancellationToken, key);
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
- public ValueTask LengthAsync(CancellationToken? cancellationToken = null)
- => _jSRuntime.InvokeAsync("eval", cancellationToken ?? CancellationToken.None, "sessionStorage.length");
+ throw;
+ }
+ }
- public ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null)
- => _jSRuntime.InvokeVoidAsync("sessionStorage.removeItem", cancellationToken ?? CancellationToken.None, key);
+ public async ValueTask RemoveItemsAsync(IEnumerable keys, CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ foreach (var key in keys)
+ {
+ await _jSRuntime.InvokeVoidAsync("sessionStorage.removeItem", cancellationToken, key);
+ }
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
- public ValueTask SetItemAsync(string key, string data, CancellationToken? cancellationToken = null)
- => _jSRuntime.InvokeVoidAsync("sessionStorage.setItem", cancellationToken ?? CancellationToken.None, key, data);
+ throw;
+ }
+ }
- public void Clear()
+ public async ValueTask SetItemAsync(string key, string data, CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ await _jSRuntime.InvokeVoidAsync("sessionStorage.setItem", cancellationToken, key, data);
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
+
+ throw;
+ }
+ }
+
+ public void Clear()
+ {
+ CheckForInProcessRuntime();
+ try
{
- CheckForInProcessRuntime();
_jSInProcessRuntime.InvokeVoid("sessionStorage.clear");
}
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
+
+ throw;
+ }
+ }
- public string GetItem(string key)
+ public string GetItem(string key)
+ {
+ CheckForInProcessRuntime();
+ try
{
- CheckForInProcessRuntime();
return _jSInProcessRuntime.Invoke("sessionStorage.getItem", key);
}
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
- public string Key(int index)
+ throw;
+ }
+ }
+
+ public string Key(int index)
+ {
+ CheckForInProcessRuntime();
+ try
{
- CheckForInProcessRuntime();
return _jSInProcessRuntime.Invoke("sessionStorage.key", index);
}
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
- public bool ContainKey(string key)
+ throw;
+ }
+ }
+
+ public IEnumerable Keys()
+ {
+ CheckForInProcessRuntime();
+ try
+ {
+ return _jSInProcessRuntime.Invoke>("eval", "Object.keys(sessionStorage)");
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
+
+ throw;
+ }
+ }
+
+ public bool ContainKey(string key)
+ {
+ CheckForInProcessRuntime();
+ try
{
- CheckForInProcessRuntime();
return _jSInProcessRuntime.Invoke("sessionStorage.hasOwnProperty", key);
}
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
- public int Length()
+ throw;
+ }
+ }
+
+ public int Length()
+ {
+ CheckForInProcessRuntime();
+ try
{
- CheckForInProcessRuntime();
return _jSInProcessRuntime.Invoke("eval", "sessionStorage.length");
}
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
+
+ throw;
+ }
+ }
+
+ public void RemoveItem(string key)
+ {
+ CheckForInProcessRuntime();
+ try
+ {
+ _jSInProcessRuntime.InvokeVoid("sessionStorage.removeItem", key);
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
- public void RemoveItem(string key)
+ throw;
+ }
+ }
+
+ public void RemoveItems(IEnumerable keys)
+ {
+ CheckForInProcessRuntime();
+ try
{
- CheckForInProcessRuntime();
- _jSInProcessRuntime.InvokeVoidAsync("sessionStorage.removeItem", key);
+ foreach (var key in keys)
+ {
+ _jSInProcessRuntime.InvokeVoid("sessionStorage.removeItem", key);
+ }
+ }
+ catch (Exception exception)
+ {
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
+
+ throw;
}
+ }
- public void SetItem(string key, string data)
+ public void SetItem(string key, string data)
+ {
+ CheckForInProcessRuntime();
+ try
{
- CheckForInProcessRuntime();
_jSInProcessRuntime.InvokeVoid("sessionStorage.setItem", key, data);
}
-
- private void CheckForInProcessRuntime()
+ catch (Exception exception)
{
- if (_jSInProcessRuntime == null)
- throw new InvalidOperationException("IJSInProcessRuntime not available");
+ if (IsStorageDisabledException(exception))
+ {
+ throw new BrowserStorageDisabledException(StorageNotAvailableMessage, exception);
+ }
+
+ throw;
}
}
+
+ private void CheckForInProcessRuntime()
+ {
+ if (_jSInProcessRuntime == null)
+ throw new InvalidOperationException("IJSInProcessRuntime not available");
+ }
+
+ private static bool IsStorageDisabledException(Exception exception)
+ => exception.Message.Contains("Failed to read the 'sessionStorage' property from 'Window'");
}
diff --git a/src/Blazored.SessionStorage/ChangedEventArgs.cs b/src/Blazored.SessionStorage/ChangedEventArgs.cs
index fae2781..f20fba4 100644
--- a/src/Blazored.SessionStorage/ChangedEventArgs.cs
+++ b/src/Blazored.SessionStorage/ChangedEventArgs.cs
@@ -1,12 +1,11 @@
using System.Diagnostics.CodeAnalysis;
-namespace Blazored.SessionStorage
+namespace Blazored.SessionStorage;
+
+[ExcludeFromCodeCoverage]
+public class ChangedEventArgs
{
- [ExcludeFromCodeCoverage]
- public class ChangedEventArgs
- {
- public string Key { get; set; }
- public object OldValue { get; set; }
- public object NewValue { get; set; }
- }
+ public string Key { get; set; }
+ public object OldValue { get; set; }
+ public object NewValue { get; set; }
}
\ No newline at end of file
diff --git a/src/Blazored.SessionStorage/ChangingEventArgs.cs b/src/Blazored.SessionStorage/ChangingEventArgs.cs
index 047a3e3..032c9e4 100644
--- a/src/Blazored.SessionStorage/ChangingEventArgs.cs
+++ b/src/Blazored.SessionStorage/ChangingEventArgs.cs
@@ -1,11 +1,10 @@
using System;
using System.Diagnostics.CodeAnalysis;
-namespace Blazored.SessionStorage
+namespace Blazored.SessionStorage;
+
+[ExcludeFromCodeCoverage]
+public class ChangingEventArgs : ChangedEventArgs
{
- [ExcludeFromCodeCoverage]
- public class ChangingEventArgs : ChangedEventArgs
- {
- public bool Cancel { get; set; }
- }
-}
+ public bool Cancel { get; set; }
+}
\ No newline at end of file
diff --git a/src/Blazored.SessionStorage/Exceptions/BrowserStorageDisabledException.cs b/src/Blazored.SessionStorage/Exceptions/BrowserStorageDisabledException.cs
new file mode 100644
index 0000000..212a658
--- /dev/null
+++ b/src/Blazored.SessionStorage/Exceptions/BrowserStorageDisabledException.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Blazored.SessionStorage.Exceptions;
+
+public class BrowserStorageDisabledException : Exception
+{
+ public BrowserStorageDisabledException()
+ {
+ }
+
+ public BrowserStorageDisabledException(string message) : base(message)
+ {
+ }
+
+ public BrowserStorageDisabledException(string message, Exception inner) : base(message, inner)
+ {
+ }
+}
diff --git a/src/Blazored.SessionStorage/ISessionStorageService.cs b/src/Blazored.SessionStorage/ISessionStorageService.cs
index c61c98c..e35d989 100644
--- a/src/Blazored.SessionStorage/ISessionStorageService.cs
+++ b/src/Blazored.SessionStorage/ISessionStorageService.cs
@@ -1,75 +1,99 @@
using System;
+using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.JSInterop;
-namespace Blazored.SessionStorage
+namespace Blazored.SessionStorage;
+
+public interface ISessionStorageService
{
- public interface ISessionStorageService
- {
- ///
- /// Clears all data from session storage.
- ///
- /// A representing the completion of the operation.
- ValueTask ClearAsync(CancellationToken? cancellationToken = null);
+ ///
+ /// Clears all data from session storage.
+ ///
+ /// A representing the completion of the operation.
+ ValueTask ClearAsync(CancellationToken cancellationToken = default);
- ///
- /// Retrieve the specified data from session storage and deseralise it to the specfied type.
- ///
- /// A value specifying the name of the session storage slot to use
- /// A representing the completion of the operation.
- ValueTask GetItemAsync(string key, CancellationToken? cancellationToken = null);
+ ///
+ /// Retrieve the specified data from session storage and deseralise it to the specfied type.
+ ///
+ /// A value specifying the name of the session storage slot to use
+ /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts () from being applied.
+ /// A representing the completion of the operation.
+ ValueTask GetItemAsync(string key, CancellationToken cancellationToken = default);
- ///
- /// Retrieve the specified data from session storage as a .
- ///
- /// A value specifying the name of the storage slot to use
- /// A representing the completion of the operation.
- ValueTask GetItemAsStringAsync(string key, CancellationToken? cancellationToken = null);
+ ///
+ /// Retrieve the specified data from session storage as a .
+ ///
+ /// A value specifying the name of the storage slot to use
+ /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts () from being applied.
+ /// A representing the completion of the operation.
+ ValueTask GetItemAsStringAsync(string key, CancellationToken cancellationToken = default);
- ///
- /// Return the name of the key at the specified .
- ///
- ///
- /// A representing the completion of the operation.
- ValueTask KeyAsync(int index, CancellationToken? cancellationToken = null);
+ ///
+ /// Return the name of the key at the specified .
+ ///
+ ///
+ /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts () from being applied.
+ /// A representing the completion of the operation.
+ ValueTask KeyAsync(int index, CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns a collection of strings representing the names of the keys in the Session storage.
+ ///
+ /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts () from being applied.
+ /// A representing the completion of the operation.
+ ValueTask> KeysAsync(CancellationToken cancellationToken = default);
- ///
- /// Checks if the exists in session storage, but does not check its value.
- ///
- /// A value specifying the name of the storage slot to use
- /// A representing the completion of the operation.
- ValueTask ContainKeyAsync(string key, CancellationToken? cancellationToken = null);
+ ///
+ /// Checks if the exists in session storage, but does not check its value.
+ ///
+ /// A value specifying the name of the storage slot to use
+ /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts () from being applied.
+ /// A representing the completion of the operation.
+ ValueTask ContainKeyAsync(string key, CancellationToken cancellationToken = default);
- ///
- /// The number of items stored in session storage.
- ///
- /// A representing the completion of the operation.
- ValueTask LengthAsync(CancellationToken? cancellationToken = null);
+ ///
+ /// The number of items stored in session storage.
+ ///
+ /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts () from being applied.
+ /// A representing the completion of the operation.
+ ValueTask LengthAsync(CancellationToken cancellationToken = default);
- ///
- /// Remove the data with the specified .
- ///
- /// A value specifying the name of the storage slot to use
- /// A representing the completion of the operation.
- ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null);
+ ///
+ /// Remove the data with the specified .
+ ///
+ /// A value specifying the name of the storage slot to use
+ /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts () from being applied.
+ /// A representing the completion of the operation.
+ ValueTask RemoveItemAsync(string key, CancellationToken cancellationToken = default);
+
+ ///
+ /// Removes a collection of .
+ ///
+ /// A IEnumerable collection of strings specifying the name of the storage slot to remove
+ /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts () from being applied.
+ /// A representing the completion of the operation.
+ ValueTask RemoveItemsAsync(IEnumerable keys, CancellationToken cancellationToken = default);
- ///
- /// Sets or updates the in session storage with the specified .
- ///
- /// A value specifying the name of the storage slot to use
- /// The data to be saved
- /// A representing the completion of the operation.
- ValueTask SetItemAsync(string key, T data, CancellationToken? cancellationToken = null);
+ ///
+ /// Sets or updates the in session storage with the specified .
+ ///
+ /// A value specifying the name of the storage slot to use
+ /// The data to be saved
+ /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts () from being applied.
+ /// A representing the completion of the operation.
+ ValueTask SetItemAsync(string key, T data, CancellationToken cancellationToken = default);
- ///
- /// Sets or updates the in session storage with the specified . Does not serialize the value before storing.
- ///
- /// A value specifying the name of the storage slot to use
- /// The string to be saved
- ///
- ValueTask SetItemAsStringAsync(string key, string data, CancellationToken? cancellationToken = null);
+ ///
+ /// Sets or updates the in session storage with the specified . Does not serialize the value before storing.
+ ///
+ /// A value specifying the name of the storage slot to use
+ /// The string to be saved
+ /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts () from being applied.
+ /// A representing the completion of the operation.
+ ValueTask SetItemAsStringAsync(string key, string data, CancellationToken cancellationToken = default);
- event EventHandler Changing;
- event EventHandler Changed;
- }
+ event EventHandler Changing;
+ event EventHandler Changed;
}
diff --git a/src/Blazored.SessionStorage/IStorageProvider.cs b/src/Blazored.SessionStorage/IStorageProvider.cs
index df476de..0bd2c7f 100644
--- a/src/Blazored.SessionStorage/IStorageProvider.cs
+++ b/src/Blazored.SessionStorage/IStorageProvider.cs
@@ -1,23 +1,26 @@
+using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-namespace Blazored.SessionStorage
+namespace Blazored.SessionStorage;
+
+internal interface IStorageProvider
{
- internal interface IStorageProvider
- {
- void Clear();
- ValueTask ClearAsync(CancellationToken? cancellationToken = null);
- bool ContainKey(string key);
- ValueTask ContainKeyAsync(string key, CancellationToken? cancellationToken = null);
- string GetItem(string key);
- ValueTask GetItemAsync(string key, CancellationToken? cancellationToken = null);
- string Key(int index);
- ValueTask KeyAsync(int index, CancellationToken? cancellationToken = null);
- int Length();
- ValueTask LengthAsync(CancellationToken? cancellationToken = null);
- void RemoveItem(string key);
- ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null);
- void SetItem(string key, string data);
- ValueTask SetItemAsync(string key, string data, CancellationToken? cancellationToken = null);
- }
+ void Clear();
+ ValueTask ClearAsync(CancellationToken cancellationToken = default);
+ bool ContainKey(string key);
+ ValueTask ContainKeyAsync(string key, CancellationToken cancellationToken = default);
+ string GetItem(string key);
+ ValueTask GetItemAsync(string key, CancellationToken cancellationToken = default);
+ string Key(int index);
+ ValueTask KeyAsync(int index, CancellationToken cancellationToken = default);
+ IEnumerable Keys();
+ ValueTask> KeysAsync(CancellationToken cancellationToken = default);
+ int Length();
+ ValueTask LengthAsync(CancellationToken cancellationToken = default);
+ void RemoveItem(string key);
+ ValueTask RemoveItemAsync(string key, CancellationToken cancellationToken = default);
+ ValueTask RemoveItemsAsync(IEnumerable keys, CancellationToken cancellationToken = default);
+ void SetItem(string key, string data);
+ ValueTask SetItemAsync(string key, string data, CancellationToken cancellationToken = default);
}
diff --git a/src/Blazored.SessionStorage/ISyncSessionStorageService.cs b/src/Blazored.SessionStorage/ISyncSessionStorageService.cs
index 0017e89..d972a1a 100644
--- a/src/Blazored.SessionStorage/ISyncSessionStorageService.cs
+++ b/src/Blazored.SessionStorage/ISyncSessionStorageService.cs
@@ -1,70 +1,82 @@
using System;
+using System.Collections.Generic;
-namespace Blazored.SessionStorage
+namespace Blazored.SessionStorage;
+
+public interface ISyncSessionStorageService
{
- public interface ISyncSessionStorageService
- {
- ///
- /// Clears all data from session storage.
- ///
- void Clear();
+ ///
+ /// Clears all data from session storage.
+ ///
+ void Clear();
- ///
- /// Retrieve the specified data from session storage as a .
- ///
- /// A value specifying the name of the session storage slot to use
- /// The data from the specified as a
- T GetItem(string key);
+ ///
+ /// Retrieve the specified data from session storage as a .
+ ///
+ /// A value specifying the name of the session storage slot to use
+ /// The data from the specified as a
+ T GetItem(string key);
- ///
- /// Retrieve the specified data from session storage as a .
- ///
- /// A value specifying the name of the storage slot to use
- /// The data associated with the specified as a
- string GetItemAsString(string key);
+ ///
+ /// Retrieve the specified data from session storage as a .
+ ///
+ /// A value specifying the name of the storage slot to use
+ /// The data associated with the specified as a
+ string GetItemAsString(string key);
- ///
- /// Return the name of the key at the specified .
- ///
- ///
- /// The name of the key at the specified
- string Key(int index);
+ ///
+ /// Return the name of the key at the specified .
+ ///
+ ///
+ /// The name of the key at the specified
+ string Key(int index);
+
+ ///
+ /// Get the keys of all items stored in session storage.
+ ///
+ /// The keys of all items stored in session storage
+ IEnumerable Keys();
- ///
- /// Checks if the exists in session storage, but does not check its value.
- ///
- /// A value specifying the name of the storage slot to use
- /// Boolean indicating if the specified exists
- bool ContainKey(string key);
+ ///
+ /// Checks if the exists in session storage, but does not check its value.
+ ///
+ /// A value specifying the name of the storage slot to use
+ /// Boolean indicating if the specified exists
+ bool ContainKey(string key);
- ///
- /// The number of items stored in session storage.
- ///
- /// The number of items stored in session storage
- int Length();
+ ///
+ /// The number of items stored in session storage.
+ ///
+ /// The number of items stored in session storage
+ int Length();
- ///
- /// Remove the data with the specified .
- ///
- /// A value specifying the name of the storage slot to use
- void RemoveItem(string key);
+ ///
+ /// Remove the data with the specified .
+ ///
+ /// A value specifying the name of the storage slot to use
+ void RemoveItem(string key);
+
+ ///
+ /// Removes a collection of .
+ ///
+ /// A IEnumerable collection of strings specifying the name of the storage slot to remove
+ void RemoveItems(IEnumerable keys);
- ///
- /// Sets or updates the in session storage with the specified .
- ///
- /// A value specifying the name of the storage slot to use
- /// The data to be saved
- void SetItem(string key, T data);
+ ///
+ /// Sets or updates the in session storage with the specified .
+ ///
+ /// A value specifying the name of the storage slot to use
+ /// The data to be saved
+ void SetItem(string key, T data);
- ///
- /// Sets or updates the in session storage with the specified . Does not serialize the value before storing.
- ///
- /// A value specifying the name of the storage slot to use
- /// The string to be saved
- ///
- void SetItemAsString(string key, string data);
+ ///
+ /// Sets or updates the in session storage with the specified . Does not serialize the value before storing.
+ ///
+ /// A value specifying the name of the storage slot to use
+ /// The string to be saved
+ ///
+ void SetItemAsString(string key, string data);
- event EventHandler Changing;
- event EventHandler Changed;
- }
+ event EventHandler Changing;
+ event EventHandler Changed;
}
diff --git a/src/Blazored.SessionStorage/JsonConverters/TimespanJsonConverter.cs b/src/Blazored.SessionStorage/JsonConverters/TimespanJsonConverter.cs
index b67e0a8..2a81538 100644
--- a/src/Blazored.SessionStorage/JsonConverters/TimespanJsonConverter.cs
+++ b/src/Blazored.SessionStorage/JsonConverters/TimespanJsonConverter.cs
@@ -5,39 +5,38 @@
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
-namespace Blazored.SessionStorage.JsonConverters
+namespace Blazored.SessionStorage.JsonConverters;
+
+///
+/// The new Json.NET doesn't support Timespan at this time
+/// https://github.com/dotnet/corefx/issues/38641
+///
+public class TimespanJsonConverter : JsonConverter
{
///
- /// The new Json.NET doesn't support Timespan at this time
- /// https://github.com/dotnet/corefx/issues/38641
+ /// Format: Days.Hours:Minutes:Seconds:Milliseconds
///
- public class TimespanJsonConverter : JsonConverter
- {
- ///
- /// Format: Days.Hours:Minutes:Seconds:Milliseconds
- ///
- public const string TimeSpanFormatString = @"d\.hh\:mm\:ss\:FFF";
+ public const string TimeSpanFormatString = @"d\.hh\:mm\:ss\:FFF";
- public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ var s = reader.GetString();
+ if (string.IsNullOrWhiteSpace(s))
{
- var s = reader.GetString();
- if (string.IsNullOrWhiteSpace(s))
- {
- return TimeSpan.Zero;
- }
-
- if (!TimeSpan.TryParseExact(s, TimeSpanFormatString, null, out var parsedTimeSpan))
- {
- throw new FormatException($"Input timespan is not in an expected format : expected {Regex.Unescape(TimeSpanFormatString)}. Please retrieve this key as a string and parse manually.");
- }
-
- return parsedTimeSpan;
+ return TimeSpan.Zero;
}
- public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
+ if (!TimeSpan.TryParseExact(s, TimeSpanFormatString, null, out var parsedTimeSpan))
{
- var timespanFormatted = $"{value.ToString(TimeSpanFormatString)}";
- writer.WriteStringValue(timespanFormatted);
+ throw new FormatException($"Input timespan is not in an expected format : expected {Regex.Unescape(TimeSpanFormatString)}. Please retrieve this key as a string and parse manually.");
}
+
+ return parsedTimeSpan;
+ }
+
+ public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
+ {
+ var timespanFormatted = $"{value.ToString(TimeSpanFormatString)}";
+ writer.WriteStringValue(timespanFormatted);
}
}
diff --git a/src/Blazored.SessionStorage/Serialization/IJsonSerializer.cs b/src/Blazored.SessionStorage/Serialization/IJsonSerializer.cs
index 9bccf18..e1a99c5 100644
--- a/src/Blazored.SessionStorage/Serialization/IJsonSerializer.cs
+++ b/src/Blazored.SessionStorage/Serialization/IJsonSerializer.cs
@@ -1,8 +1,7 @@
-namespace Blazored.SessionStorage.Serialization
+namespace Blazored.SessionStorage.Serialization;
+
+public interface IJsonSerializer
{
- public interface IJsonSerializer
- {
- string Serialize(T obj);
- T Deserialize(string text);
- }
+ string Serialize(T obj);
+ T Deserialize(string text);
}
diff --git a/src/Blazored.SessionStorage/Serialization/SystemTextJsonSerializer.cs b/src/Blazored.SessionStorage/Serialization/SystemTextJsonSerializer.cs
index 5ce56c0..a4b893f 100644
--- a/src/Blazored.SessionStorage/Serialization/SystemTextJsonSerializer.cs
+++ b/src/Blazored.SessionStorage/Serialization/SystemTextJsonSerializer.cs
@@ -2,26 +2,25 @@
using Microsoft.Extensions.Options;
using System.Text.Json;
-namespace Blazored.SessionStorage.Serialization
+namespace Blazored.SessionStorage.Serialization;
+
+internal class SystemTextJsonSerializer : IJsonSerializer
{
- internal class SystemTextJsonSerializer : IJsonSerializer
- {
- private readonly JsonSerializerOptions _options;
+ private readonly JsonSerializerOptions _options;
- public SystemTextJsonSerializer(IOptions options)
- {
- _options = options.Value.JsonSerializerOptions;
- }
+ public SystemTextJsonSerializer(IOptions options)
+ {
+ _options = options.Value.JsonSerializerOptions;
+ }
- public SystemTextJsonSerializer(SessionStorageOptions sessionStorageOptions)
- {
- _options = sessionStorageOptions.JsonSerializerOptions;
- }
+ public SystemTextJsonSerializer(SessionStorageOptions sessionStorageOptions)
+ {
+ _options = sessionStorageOptions.JsonSerializerOptions;
+ }
- public T Deserialize(string data)
- => JsonSerializer.Deserialize(data, _options);
+ public T Deserialize(string data)
+ => JsonSerializer.Deserialize(data, _options);
- public string Serialize(T data)
- => JsonSerializer.Serialize(data, _options);
- }
-}
+ public string Serialize(T data)
+ => JsonSerializer.Serialize(data, _options);
+}
\ No newline at end of file
diff --git a/src/Blazored.SessionStorage/ServiceCollectionExtensions.cs b/src/Blazored.SessionStorage/ServiceCollectionExtensions.cs
index 9b1e2bf..795a92c 100644
--- a/src/Blazored.SessionStorage/ServiceCollectionExtensions.cs
+++ b/src/Blazored.SessionStorage/ServiceCollectionExtensions.cs
@@ -5,26 +5,54 @@
using Blazored.SessionStorage.StorageOptions;
using Microsoft.Extensions.DependencyInjection;
-namespace Blazored.SessionStorage
+namespace Blazored.SessionStorage;
+
+[ExcludeFromCodeCoverage]
+public static class ServiceCollectionExtensions
{
- [ExcludeFromCodeCoverage]
- public static class ServiceCollectionExtensions
- {
- public static IServiceCollection AddBlazoredSessionStorage(this IServiceCollection services)
- => AddBlazoredSessionStorage(services, null);
+ public static IServiceCollection AddBlazoredSessionStorage(this IServiceCollection services)
+ => AddBlazoredSessionStorage(services, null);
- public static IServiceCollection AddBlazoredSessionStorage(this IServiceCollection services, Action configure)
- {
- return services
- .AddScoped()
- .AddScoped()
- .AddScoped()
- .AddScoped()
- .Configure(configureOptions =>
- {
- configure?.Invoke(configureOptions);
- configureOptions.JsonSerializerOptions.Converters.Add(new TimespanJsonConverter());
- });
- }
+ public static IServiceCollection AddBlazoredSessionStorage(this IServiceCollection services, Action configure)
+ {
+ return services
+ .AddScoped()
+ .AddScoped()
+ .AddScoped()
+ .AddScoped()
+ .Configure(configureOptions =>
+ {
+ configure?.Invoke(configureOptions);
+ configureOptions.JsonSerializerOptions.Converters.Add(new TimespanJsonConverter());
+ });
+ }
+
+ ///
+ /// Registers the Blazored SessionStorage services as singletons. This should only be used in Blazor WebAssembly applications.
+ /// Using this in Blazor Server applications will cause unexpected and potentially dangerous behaviour.
+ ///
+ ///
+ public static IServiceCollection AddBlazoredSessionStorageAsSingleton(this IServiceCollection services)
+ => AddBlazoredSessionStorageAsSingleton(services, null);
+
+ ///
+ /// Registers the Blazored SessionStorage services as singletons. This should only be used in Blazor WebAssembly applications.
+ /// Using this in Blazor Server applications will cause unexpected and potentially dangerous behaviour.
+ ///
+ ///
+ ///
+ ///
+ public static IServiceCollection AddBlazoredSessionStorageAsSingleton(this IServiceCollection services, Action configure)
+ {
+ return services
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .Configure(configureOptions =>
+ {
+ configure?.Invoke(configureOptions);
+ configureOptions.JsonSerializerOptions.Converters.Add(new TimespanJsonConverter());
+ });
}
}
diff --git a/src/Blazored.SessionStorage/SessionStorageService.cs b/src/Blazored.SessionStorage/SessionStorageService.cs
index d020994..c9b429d 100644
--- a/src/Blazored.SessionStorage/SessionStorageService.cs
+++ b/src/Blazored.SessionStorage/SessionStorageService.cs
@@ -1,269 +1,289 @@
using System;
+using System.Collections.Generic;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Blazored.SessionStorage.Serialization;
-namespace Blazored.SessionStorage
+namespace Blazored.SessionStorage;
+
+internal class SessionStorageService : ISessionStorageService, ISyncSessionStorageService
{
- internal class SessionStorageService : ISessionStorageService, ISyncSessionStorageService
+ private readonly IStorageProvider _storageProvider;
+ private readonly IJsonSerializer _serializer;
+
+ public SessionStorageService(IStorageProvider storageProvider, IJsonSerializer serializer)
{
- private readonly IStorageProvider _storageProvider;
- private readonly IJsonSerializer _serializer;
+ _storageProvider = storageProvider;
+ _serializer = serializer;
+ }
- public SessionStorageService(IStorageProvider storageProvider, IJsonSerializer serializer)
- {
- _storageProvider = storageProvider;
- _serializer = serializer;
- }
+ public ValueTask RemoveItemsAsync(IEnumerable keys, CancellationToken cancellationToken = default)
+ => _storageProvider.RemoveItemsAsync(keys, cancellationToken);
- public async ValueTask SetItemAsync(string key, T data, CancellationToken? cancellationToken = null)
- {
- if (string.IsNullOrWhiteSpace(key))
- throw new ArgumentNullException(nameof(key));
+ public async ValueTask SetItemAsync(string key, T data, CancellationToken cancellationToken = default)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentNullException(nameof(key));
- var e = await RaiseOnChangingAsync(key, data).ConfigureAwait(false);
+ var e = await RaiseOnChangingAsync(key, data).ConfigureAwait(false);
- if (e.Cancel)
- return;
+ if (e.Cancel)
+ return;
- var serialisedData = _serializer.Serialize(data);
- await _storageProvider.SetItemAsync(key, serialisedData, cancellationToken).ConfigureAwait(false);
+ var serialisedData = _serializer.Serialize(data);
+ await _storageProvider.SetItemAsync(key, serialisedData, cancellationToken).ConfigureAwait(false);
- RaiseOnChanged(key, e.OldValue, data);
- }
+ RaiseOnChanged(key, e.OldValue, data);
+ }
- public async ValueTask SetItemAsStringAsync(string key, string data, CancellationToken? cancellationToken = null)
- {
- if (string.IsNullOrWhiteSpace(key))
- throw new ArgumentNullException(nameof(key));
+ public async ValueTask SetItemAsStringAsync(string key, string data, CancellationToken cancellationToken = default)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentNullException(nameof(key));
- if (data is null)
- throw new ArgumentNullException(nameof(data));
+ if (data is null)
+ throw new ArgumentNullException(nameof(data));
- var e = await RaiseOnChangingAsync(key, data).ConfigureAwait(false);
+ var e = await RaiseOnChangingAsync(key, data).ConfigureAwait(false);
- if (e.Cancel)
- return;
+ if (e.Cancel)
+ return;
- await _storageProvider.SetItemAsync(key, data, cancellationToken).ConfigureAwait(false);
+ await _storageProvider.SetItemAsync(key, data, cancellationToken).ConfigureAwait(false);
- RaiseOnChanged(key, e.OldValue, data);
- }
+ RaiseOnChanged(key, e.OldValue, data);
+ }
+
+ public async ValueTask GetItemAsync(string key, CancellationToken cancellationToken = default)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentNullException(nameof(key));
- public async ValueTask GetItemAsync(string key, CancellationToken? cancellationToken = null)
+ var serialisedData = await _storageProvider.GetItemAsync(key, cancellationToken).ConfigureAwait(false);
+
+ if (string.IsNullOrWhiteSpace(serialisedData))
+ return default;
+
+ try
{
- if (string.IsNullOrWhiteSpace(key))
- throw new ArgumentNullException(nameof(key));
-
- var serialisedData = await _storageProvider.GetItemAsync(key, cancellationToken).ConfigureAwait(false);
-
- if (string.IsNullOrWhiteSpace(serialisedData))
- return default;
-
- try
- {
- return _serializer.Deserialize(serialisedData);
- }
- catch (JsonException e) when (e.Path == "$" && typeof(T) == typeof(string))
- {
- // For backward compatibility return the plain string.
- // On the next save a correct value will be stored and this Exception will not happen again, for this 'key'
- return (T)(object)serialisedData;
- }
+ return _serializer.Deserialize(serialisedData);
}
-
- public ValueTask GetItemAsStringAsync(string key, CancellationToken? cancellationToken = null)
+ catch (JsonException e) when (e.Path == "$" && typeof(T) == typeof(string))
{
- if (string.IsNullOrWhiteSpace(key))
- throw new ArgumentNullException(nameof(key));
-
- return _storageProvider.GetItemAsync(key, cancellationToken);
+ // For backward compatibility return the plain string.
+ // On the next save a correct value will be stored and this Exception will not happen again, for this 'key'
+ return (T)(object)serialisedData;
}
+ }
- public ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null)
- {
- if (string.IsNullOrWhiteSpace(key))
- throw new ArgumentNullException(nameof(key));
+ public ValueTask GetItemAsStringAsync(string key, CancellationToken cancellationToken = default)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentNullException(nameof(key));
- return _storageProvider.RemoveItemAsync(key, cancellationToken);
- }
+ return _storageProvider.GetItemAsync(key, cancellationToken);
+ }
- public ValueTask ClearAsync(CancellationToken? cancellationToken = null)
- => _storageProvider.ClearAsync(cancellationToken);
+ public ValueTask RemoveItemAsync(string key, CancellationToken cancellationToken = default)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentNullException(nameof(key));
- public ValueTask LengthAsync(CancellationToken? cancellationToken = null)
- => _storageProvider.LengthAsync(cancellationToken);
+ return _storageProvider.RemoveItemAsync(key, cancellationToken);
+ }
- public ValueTask KeyAsync(int index, CancellationToken? cancellationToken = null)
- => _storageProvider.KeyAsync(index, cancellationToken);
+ public ValueTask ClearAsync(CancellationToken cancellationToken = default)
+ => _storageProvider.ClearAsync(cancellationToken);
- public ValueTask ContainKeyAsync(string key, CancellationToken? cancellationToken = null)
- => _storageProvider.ContainKeyAsync(key, cancellationToken);
+ public ValueTask LengthAsync(CancellationToken cancellationToken = default)
+ => _storageProvider.LengthAsync(cancellationToken);
- public void SetItem(string key, T data)
- {
- if (string.IsNullOrWhiteSpace(key))
- throw new ArgumentNullException(nameof(key));
+ public ValueTask KeyAsync(int index, CancellationToken cancellationToken = default)
+ => _storageProvider.KeyAsync(index, cancellationToken);
- var e = RaiseOnChangingSync(key, data);
+ public ValueTask> KeysAsync(CancellationToken cancellationToken = default)
+ => _storageProvider.KeysAsync(cancellationToken);
- if (e.Cancel)
- return;
+ public ValueTask ContainKeyAsync(string key, CancellationToken cancellationToken = default)
+ => _storageProvider.ContainKeyAsync(key, cancellationToken);
- var serialisedData = _serializer.Serialize(data);
- _storageProvider.SetItem(key, serialisedData);
+ public void SetItem(string key, T data)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentNullException(nameof(key));
- RaiseOnChanged(key, e.OldValue, data);
- }
+ var e = RaiseOnChangingSync(key, data);
- public void SetItemAsString(string key, string data)
- {
- if (string.IsNullOrWhiteSpace(key))
- throw new ArgumentNullException(nameof(key));
+ if (e.Cancel)
+ return;
- if (data is null)
- throw new ArgumentNullException(nameof(data));
+ var serialisedData = _serializer.Serialize(data);
+ _storageProvider.SetItem(key, serialisedData);
- var e = RaiseOnChangingSync(key, data);
+ RaiseOnChanged(key, e.OldValue, data);
+ }
- if (e.Cancel)
- return;
+ public void SetItemAsString(string key, string data)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentNullException(nameof(key));
- _storageProvider.SetItem(key, data);
+ if (data is null)
+ throw new ArgumentNullException(nameof(data));
- RaiseOnChanged(key, e.OldValue, data);
- }
+ var e = RaiseOnChangingSync(key, data);
+
+ if (e.Cancel)
+ return;
+
+ _storageProvider.SetItem(key, data);
+
+ RaiseOnChanged(key, e.OldValue, data);
+ }
+
+ public T GetItem(string key)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentNullException(nameof(key));
- public T GetItem(string key)
+ var serialisedData = _storageProvider.GetItem(key);
+
+ if (string.IsNullOrWhiteSpace(serialisedData))
+ return default;
+
+ try
{
- if (string.IsNullOrWhiteSpace(key))
- throw new ArgumentNullException(nameof(key));
-
- var serialisedData = _storageProvider.GetItem(key);
-
- if (string.IsNullOrWhiteSpace(serialisedData))
- return default;
-
- try
- {
- return _serializer.Deserialize(serialisedData);
- }
- catch (JsonException e) when (e.Path == "$" && typeof(T) == typeof(string))
- {
- // For backward compatibility return the plain string.
- // On the next save a correct value will be stored and this Exception will not happen again, for this 'key'
- return (T)(object)serialisedData;
- }
+ return _serializer.Deserialize(serialisedData);
}
-
- public string GetItemAsString(string key)
+ catch (JsonException e) when (e.Path == "$" && typeof(T) == typeof(string))
{
- if (string.IsNullOrWhiteSpace(key))
- throw new ArgumentNullException(nameof(key));
-
- return _storageProvider.GetItem(key);
+ // For backward compatibility return the plain string.
+ // On the next save a correct value will be stored and this Exception will not happen again, for this 'key'
+ return (T)(object)serialisedData;
}
+ }
- public void RemoveItem(string key)
- {
- if (string.IsNullOrWhiteSpace(key))
- throw new ArgumentNullException(nameof(key));
+ public string GetItemAsString(string key)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentNullException(nameof(key));
+ return _storageProvider.GetItem(key);
+ }
+
+ public void RemoveItem(string key)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentNullException(nameof(key));
+
+ _storageProvider.RemoveItem(key);
+ }
+
+ public void RemoveItems(IEnumerable keys)
+ {
+ if (keys == null)
+ throw new ArgumentNullException(nameof(keys));
+
+ foreach (var key in keys)
+ {
_storageProvider.RemoveItem(key);
}
+ }
- public void Clear()
- => _storageProvider.Clear();
+ public void Clear()
+ => _storageProvider.Clear();
- public int Length()
- => _storageProvider.Length();
+ public int Length()
+ => _storageProvider.Length();
- public string Key(int index)
- => _storageProvider.Key(index);
+ public string Key(int index)
+ => _storageProvider.Key(index);
+
+ public IEnumerable Keys()
+ => _storageProvider.Keys();
- public bool ContainKey(string key)
- => _storageProvider.ContainKey(key);
+ public bool ContainKey(string key)
+ => _storageProvider.ContainKey(key);
- public event EventHandler Changing;
- private async Task RaiseOnChangingAsync(string key, object data)
+ public event EventHandler Changing;
+ private async Task RaiseOnChangingAsync(string key, object data)
+ {
+ var e = new ChangingEventArgs
{
- var e = new ChangingEventArgs
- {
- Key = key,
- OldValue = await GetItemInternalAsync