From 5b9947f16f2a78f8ace8a3a6fc65fdbeaa30b97b Mon Sep 17 00:00:00 2001 From: Kim-SSi Date: Mon, 14 Jun 2021 01:27:02 +1200 Subject: [PATCH] Add CancellationToken support to Async methods (#146) --- .../BrowserStorageProvider.cs | 31 +++--- .../ILocalStorageService.cs | 101 +++++++++++------- src/Blazored.LocalStorage/IStorageProvider.cs | 17 +-- .../LocalStorageService.cs | 41 +++---- .../Testing/InMemoryStorageProvider.cs | 17 +-- 5 files changed, 120 insertions(+), 87 deletions(-) diff --git a/src/Blazored.LocalStorage/BrowserStorageProvider.cs b/src/Blazored.LocalStorage/BrowserStorageProvider.cs index c67de13..a229459 100644 --- a/src/Blazored.LocalStorage/BrowserStorageProvider.cs +++ b/src/Blazored.LocalStorage/BrowserStorageProvider.cs @@ -1,5 +1,6 @@ -using Microsoft.JSInterop; +using Microsoft.JSInterop; using System; +using System.Threading; using System.Threading.Tasks; namespace Blazored.LocalStorage @@ -15,26 +16,26 @@ public BrowserStorageProvider(IJSRuntime jSRuntime) _jSInProcessRuntime = jSRuntime as IJSInProcessRuntime; } - public ValueTask ClearAsync() - => _jSRuntime.InvokeVoidAsync("localStorage.clear"); + public ValueTask ClearAsync(CancellationToken? cancellationToken = null) + => _jSRuntime.InvokeVoidAsync("localStorage.clear", cancellationToken ?? CancellationToken.None); - public ValueTask GetItemAsync(string key) - => _jSRuntime.InvokeAsync("localStorage.getItem", key); + public ValueTask GetItemAsync(string key, CancellationToken? cancellationToken = null) + => _jSRuntime.InvokeAsync("localStorage.getItem", cancellationToken ?? CancellationToken.None, key); - public ValueTask KeyAsync(int index) - => _jSRuntime.InvokeAsync("localStorage.key", index); + public ValueTask KeyAsync(int index, CancellationToken? cancellationToken = null) + => _jSRuntime.InvokeAsync("localStorage.key", cancellationToken ?? CancellationToken.None, index); - public ValueTask ContainKeyAsync(string key) - => _jSRuntime.InvokeAsync("localStorage.hasOwnProperty", key); + public ValueTask ContainKeyAsync(string key, CancellationToken? cancellationToken = null) + => _jSRuntime.InvokeAsync("localStorage.hasOwnProperty", cancellationToken ?? CancellationToken.None, key); - public ValueTask LengthAsync() - => _jSRuntime.InvokeAsync("eval", "localStorage.length"); + public ValueTask LengthAsync(CancellationToken? cancellationToken = null) + => _jSRuntime.InvokeAsync("eval", cancellationToken ?? CancellationToken.None, "localStorage.length"); - public ValueTask RemoveItemAsync(string key) - => _jSRuntime.InvokeVoidAsync("localStorage.removeItem", key); + public ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null) + => _jSRuntime.InvokeVoidAsync("localStorage.removeItem", cancellationToken ?? CancellationToken.None, key); - public ValueTask SetItemAsync(string key, string data) - => _jSRuntime.InvokeVoidAsync("localStorage.setItem", key, data); + public ValueTask SetItemAsync(string key, string data, CancellationToken? cancellationToken = null) + => _jSRuntime.InvokeVoidAsync("localStorage.setItem", cancellationToken ?? CancellationToken.None, key, data); public void Clear() { diff --git a/src/Blazored.LocalStorage/ILocalStorageService.cs b/src/Blazored.LocalStorage/ILocalStorageService.cs index cc6cef2..47b9996 100644 --- a/src/Blazored.LocalStorage/ILocalStorageService.cs +++ b/src/Blazored.LocalStorage/ILocalStorageService.cs @@ -1,73 +1,102 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Blazored.LocalStorage { public interface ILocalStorageService { - /// - /// Clears all data from local storage. + /// + /// Clears all data from local storage. /// /// A representing the completion of the operation. - ValueTask ClearAsync(); + ValueTask ClearAsync(CancellationToken? cancellationToken = null); - /// - /// Retrieve the specified data from local storage and deseralise it to the specfied type. - /// - /// A value specifying the name of the local storage slot to use + /// + /// Retrieve the specified data from local storage and deseralise it to the specfied type. + /// + /// A value specifying the name of the local 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); + ValueTask GetItemAsync(string key, CancellationToken? cancellationToken = null); - /// - /// Retrieve the specified data from local storage as a . - /// - /// A value specifying the name of the storage slot to use + /// + /// Retrieve the specified data from local 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); + ValueTask GetItemAsStringAsync(string key, CancellationToken? cancellationToken = null); - /// - /// Return the name of the key at the specified . - /// - /// + /// + /// 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); + ValueTask KeyAsync(int index, CancellationToken? cancellationToken = null); /// /// Checks if the exists in local 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); + ValueTask ContainKeyAsync(string key, CancellationToken? cancellationToken = null); - /// - /// The number of items stored in local storage. - /// + /// + /// The number of items stored in local storage. + /// /// A representing the completion of the operation. - ValueTask LengthAsync(); + ValueTask LengthAsync(CancellationToken? cancellationToken = null); - /// - /// Remove the data with the specified . - /// - /// A value specifying the name of the storage slot to use + /// + /// 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); + ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null); - /// - /// Sets or updates the in local storage with the specified . - /// - /// A value specifying the name of the storage slot to use - /// The data to be saved + /// + /// Sets or updates the in local 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); + ValueTask SetItemAsync(string key, T data, CancellationToken? cancellationToken = null); /// /// Sets or updates the in local 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. + /// /// - ValueTask SetItemAsStringAsync(string key, string data); - + ValueTask SetItemAsStringAsync(string key, string data, CancellationToken? cancellationToken = null); + event EventHandler Changing; event EventHandler Changed; } diff --git a/src/Blazored.LocalStorage/IStorageProvider.cs b/src/Blazored.LocalStorage/IStorageProvider.cs index 52211a7..c0b7d19 100644 --- a/src/Blazored.LocalStorage/IStorageProvider.cs +++ b/src/Blazored.LocalStorage/IStorageProvider.cs @@ -1,22 +1,23 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace Blazored.LocalStorage { internal interface IStorageProvider { void Clear(); - ValueTask ClearAsync(); + ValueTask ClearAsync(CancellationToken? cancellationToken = null); bool ContainKey(string key); - ValueTask ContainKeyAsync(string key); + ValueTask ContainKeyAsync(string key, CancellationToken? cancellationToken = null); string GetItem(string key); - ValueTask GetItemAsync(string key); + ValueTask GetItemAsync(string key, CancellationToken? cancellationToken = null); string Key(int index); - ValueTask KeyAsync(int index); + ValueTask KeyAsync(int index, CancellationToken? cancellationToken = null); int Length(); - ValueTask LengthAsync(); + ValueTask LengthAsync(CancellationToken? cancellationToken = null); void RemoveItem(string key); - ValueTask RemoveItemAsync(string key); + ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null); void SetItem(string key, string data); - ValueTask SetItemAsync(string key, string data); + ValueTask SetItemAsync(string key, string data, CancellationToken? cancellationToken = null); } } \ No newline at end of file diff --git a/src/Blazored.LocalStorage/LocalStorageService.cs b/src/Blazored.LocalStorage/LocalStorageService.cs index 2294112..1e9a8ce 100644 --- a/src/Blazored.LocalStorage/LocalStorageService.cs +++ b/src/Blazored.LocalStorage/LocalStorageService.cs @@ -1,5 +1,6 @@ using System; using System.Text.Json; +using System.Threading; using System.Threading.Tasks; using Blazored.LocalStorage.Serialization; @@ -16,7 +17,7 @@ public LocalStorageService(IStorageProvider storageProvider, IJsonSerializer ser _serializer = serializer; } - public async ValueTask SetItemAsync(string key, T data) + public async ValueTask SetItemAsync(string key, T data, CancellationToken? cancellationToken = null) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); @@ -27,12 +28,12 @@ public async ValueTask SetItemAsync(string key, T data) return; var serialisedData = _serializer.Serialize(data); - await _storageProvider.SetItemAsync(key, serialisedData).ConfigureAwait(false); + await _storageProvider.SetItemAsync(key, serialisedData, cancellationToken).ConfigureAwait(false); RaiseOnChanged(key, e.OldValue, data); } - public async ValueTask SetItemAsStringAsync(string key, string data) + public async ValueTask SetItemAsStringAsync(string key, string data, CancellationToken? cancellationToken = null) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); @@ -45,17 +46,17 @@ public async ValueTask SetItemAsStringAsync(string key, string data) if (e.Cancel) return; - await _storageProvider.SetItemAsync(key, data).ConfigureAwait(false); + await _storageProvider.SetItemAsync(key, data, cancellationToken).ConfigureAwait(false); RaiseOnChanged(key, e.OldValue, data); } - public async ValueTask GetItemAsync(string key) + public async ValueTask GetItemAsync(string key, CancellationToken? cancellationToken = null) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); - var serialisedData = await _storageProvider.GetItemAsync(key).ConfigureAwait(false); + var serialisedData = await _storageProvider.GetItemAsync(key, cancellationToken).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(serialisedData)) return default; @@ -72,33 +73,33 @@ public async ValueTask GetItemAsync(string key) } } - public ValueTask GetItemAsStringAsync(string key) + public ValueTask GetItemAsStringAsync(string key, CancellationToken? cancellationToken = null) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); - return _storageProvider.GetItemAsync(key); + return _storageProvider.GetItemAsync(key, cancellationToken); } - public ValueTask RemoveItemAsync(string key) + public ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); - return _storageProvider.RemoveItemAsync(key); + return _storageProvider.RemoveItemAsync(key, cancellationToken); } - public ValueTask ClearAsync() - => _storageProvider.ClearAsync(); + public ValueTask ClearAsync(CancellationToken? cancellationToken = null) + => _storageProvider.ClearAsync(cancellationToken); - public ValueTask LengthAsync() - => _storageProvider.LengthAsync(); + public ValueTask LengthAsync(CancellationToken? cancellationToken = null) + => _storageProvider.LengthAsync(cancellationToken); - public ValueTask KeyAsync(int index) - => _storageProvider.KeyAsync(index); + public ValueTask KeyAsync(int index, CancellationToken? cancellationToken = null) + => _storageProvider.KeyAsync(index, cancellationToken); - public ValueTask ContainKeyAsync(string key) - => _storageProvider.ContainKeyAsync(key); + public ValueTask ContainKeyAsync(string key, CancellationToken? cancellationToken = null) + => _storageProvider.ContainKeyAsync(key, cancellationToken); public void SetItem(string key, T data) { @@ -213,12 +214,12 @@ private ChangingEventArgs RaiseOnChangingSync(string key, object data) return e; } - private async Task GetItemInternalAsync(string key) + private async Task GetItemInternalAsync(string key, CancellationToken? cancellationToken = null) { if (string.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key)); - var serialisedData = await _storageProvider.GetItemAsync(key).ConfigureAwait(false); + var serialisedData = await _storageProvider.GetItemAsync(key, cancellationToken).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(serialisedData)) return default; diff --git a/src/Blazored.LocalStorage/Testing/InMemoryStorageProvider.cs b/src/Blazored.LocalStorage/Testing/InMemoryStorageProvider.cs index 1d13a7b..c61f25c 100644 --- a/src/Blazored.LocalStorage/Testing/InMemoryStorageProvider.cs +++ b/src/Blazored.LocalStorage/Testing/InMemoryStorageProvider.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace Blazored.LocalStorage.Testing @@ -12,7 +13,7 @@ internal class InMemoryStorageProvider : IStorageProvider public void Clear() => _dataStore.Clear(); - public ValueTask ClearAsync() + public ValueTask ClearAsync(CancellationToken? cancellationToken = null) { _dataStore.Clear(); return new ValueTask(Task.CompletedTask); @@ -21,31 +22,31 @@ public ValueTask ClearAsync() public bool ContainKey(string key) => _dataStore.ContainsKey(key); - public ValueTask ContainKeyAsync(string key) + public ValueTask ContainKeyAsync(string key, CancellationToken? cancellationToken = null) => new ValueTask(ContainKey(key)); public string GetItem(string key) => _dataStore.ContainsKey(key) ? _dataStore[key] : default; - public ValueTask GetItemAsync(string key) + public ValueTask GetItemAsync(string key, CancellationToken? cancellationToken = null) => new ValueTask(GetItem(key)); public string Key(int index) => index > _dataStore.Count - 1 ? default : _dataStore.ElementAt(index).Key; - public ValueTask KeyAsync(int index) + public ValueTask KeyAsync(int index, CancellationToken? cancellationToken = null) => new ValueTask(Key(index)); public int Length() => _dataStore.Count; - public ValueTask LengthAsync() + public ValueTask LengthAsync(CancellationToken? cancellationToken = null) => new ValueTask(Length()); public void RemoveItem(string key) => _dataStore.Remove(key); - public ValueTask RemoveItemAsync(string key) + public ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null) { RemoveItem(key); return new ValueTask(Task.CompletedTask); @@ -63,7 +64,7 @@ public void SetItem(string key, string data) } } - public ValueTask SetItemAsync(string key, string data) + public ValueTask SetItemAsync(string key, string data, CancellationToken? cancellationToken = null) { SetItem(key, data); return new ValueTask(Task.CompletedTask);