Releases: IEvangelist/blazorators
v1.3.0 Dependency Generation
- Add
Blazor.Geolocation.WebAssembly
library. - Update sample consuming project to show
geolocation
working. - Support generating dependencies from callbacks.
Full Changelog: 1.2.0...1.3.0
Release v1.2.0 services and DI
As an example, the official Blazor.LocalStorage.WebAssembly
package consumes the Blazor.SourceGenerators
package. It exposes extension methods specific to Blazor WebAssembly and the localStorage
Web API.
Consider the SynchronousLocalStorageExtensions.cs C# file:
// Copyright (c) David Pine. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.JSInterop;
/// <summary>
/// Source generated extension methods on the <see cref="IJSInProcessRuntime"/> implementation.
/// </summary>
[JSAutoGenericInterop(
TypeName = "Storage",
Implementation = "window.localStorage",
Url = "https://developer.mozilla.org/docs/Web/API/Window/localStorage",
GenericMethodDescriptors = new[]
{
"getItem",
"setItem:value"
})]
internal static partial class SynchronousLocalStorageExtensions
{
}
This code designates itself into the Microsoft.JSInterop
namespace, making all of the source generated extensions available to anyone consumer who uses types from this namespace. It uses the JSAutoInterop
to specify:
TypeName = "Storage"
: sets the type toStorage
.Implementation = "window.localStorage"
: expresses how to locate the implementation of the specified type from the globally scopedwindow
object, this is thelocalStorage
implementation.Url
: sets the URL for the implementation.GenericMethodDescriptors
: Defines the methods that should support generics as part of their source-generation. ThelocalStorage.getItem
is specified to return a genericTResult
type, and thelocalStorage.setItem
has its parameter with a name ofvalue
specified as a genericTArg
type.
The generic method descriptors syntax is:
"methodName"
for generic return type and"methodName:parameterName"
for generic parameter type.
The file needs to define an extension class and needs to be partial
, for example; internal static partial class
. Decorating the class with the JSAutoInterop
(or `JSAutoGenericInterop) attribute will source generate the following C# code:
// Copyright (c) David Pine. All rights reserved.
// Licensed under the MIT License:
// https://github.com/IEvangelist/blazorators/blob/main/LICENSE
// Auto-generated by blazorators.
using Blazor.Serialization.Extensions;
using System.Text.Json;
#nullable enable
namespace Microsoft.JSInterop;
internal static partial class SynchronousLocalStorageExtensions
{
/// <summary>
/// Source generated extension method implementation of <c>window.localStorage.clear</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/clear"></a>
/// </summary>
public static void Clear(
this IJSInProcessRuntime javaScript) =>
javaScript.InvokeVoid("window.localStorage.clear");
/// <summary>
/// Source generated extension method implementation of <c>window.localStorage.getItem</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/getItem"></a>
/// </summary>
public static TResult? GetItem<TResult>(
this IJSInProcessRuntime javaScript,
string key,
JsonSerializerOptions? options = null) =>
javaScript.Invoke<string?>(
"window.localStorage.getItem",
key)
.FromJson<TResult>(options);
/// <summary>
/// Source generated extension method implementation of <c>window.localStorage.key</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/key"></a>
/// </summary>
public static string? Key(
this IJSInProcessRuntime javaScript,
double index) =>
javaScript.Invoke<string?>(
"window.localStorage.key",
index);
/// <summary>
/// Source generated extension method implementation of <c>window.localStorage.removeItem</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/removeItem"></a>
/// </summary>
public static void RemoveItem(
this IJSInProcessRuntime javaScript,
string key) =>
javaScript.InvokeVoid(
"window.localStorage.removeItem",
key);
/// <summary>
/// Source generated extension method implementation of <c>window.localStorage.setItem</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/setItem"></a>
/// </summary>
public static void SetItem<TArg>(
this IJSInProcessRuntime javaScript,
string key,
TArg value,
JsonSerializerOptions? options = null) =>
javaScript.InvokeVoid(
"window.localStorage.setItem",
key,
value.ToJson(options));
/// <summary>
/// Source generated extension method implementation of <c>window.localStorage.length</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/length"></a>
/// </summary>
public static double Length(
this IJSInProcessRuntime javaScript) =>
javaScript.Invoke<double>(
"eval", "window.localStorage.length");
}
These internal extension methods rely on the IJSInProcessRuntime
to perform JavaScript interop. From the given TypeName
and corresponding Implementation
, the following code is also generated:
IStorage.g.cs
: The interface for the correspondingStorage
Web API surface area.LocalStorge.g.cs
: Theinternal
implementation of theIStorage
interface.LocalStorageServiceCollectionExtensions.g.cs
: Extension methods to add theIStorage
service to the dependency injectionIServiceCollection
.
Here is the source generated IStorage.g.cs
:
using Blazor.Serialization.Extensions;
using System.Text.Json;
#nullable enable
namespace Microsoft.JSInterop;
/// <summary>
/// Source generated interface definition of the <c>Storage</c> type.
/// </summary>
public interface IStorage
{
/// <summary>
/// Source generated implementation of <c>window.localStorage.clear</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/clear"></a>
/// </summary>
void Clear();
/// <summary>
/// Source generated implementation of <c>window.localStorage.getItem</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/getItem"></a>
/// </summary>
TResult? GetItem<TResult>(string key, JsonSerializerOptions? options = null);
/// <summary>
/// Source generated implementation of <c>window.localStorage.key</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/key"></a>
/// </summary>
string? Key(double index);
/// <summary>
/// Source generated implementation of <c>window.localStorage.removeItem</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/removeItem"></a>
/// </summary>
void RemoveItem(string key);
/// <summary>
/// Source generated implementation of <c>window.localStorage.setItem</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/setItem"></a>
/// </summary>
void SetItem<TArg>(string key, TArg value, JsonSerializerOptions? options = null);
/// <summary>
/// Source generated implementation of <c>window.localStorage.length</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Storage/length"></a>
/// </summary>
double Length { get; }
}
Here is the source generated LocalStorage
implementation:
using Blazor.Serialization.Extensions;
using System.Text.Json;
#nullable enable
namespace Microsoft.JSInterop;
/// <inheritdoc/>
internal class LocalStorage : IStorage
{
private readonly IJSInProcessRuntime _javaScript = null!;
public LocalStorage(IJSInProcessRuntime javaScript) => _javaScript = javaScript;
/// <inheritdoc/>
void IStorage.Clear() => _javaScript.Clear();
/// <inheritdoc/>
TResult? IStorage.GetItem<TResult>(string key, JsonSerializerOptions? options)
where TResult : default => _javaScript.GetItem<TResult>(key, options);
/// <inheritdoc/>
string? IStorage.Key(double index) => _javaScript.Key(index);
/// <inheritdoc/>
void IStorage.RemoveItem(string key) => _javaScript.RemoveItem(key);
/// <inheritdoc/>
void IStorage.SetItem<TArg>(string key, TArg value, JsonSerializerOptions? options) =>
_javaScript.SetItem(key, value, options);
/// <inheritdoc/>
double IStorage.Length => _javaScript.Length();
}
Finally, here is the source generated service collection extension methods:
using Microsoft.JSInterop;
namespace Microsoft.Extensions.DependencyInjection;
/// <summary></summary>
public static class LocalStorageServiceCollectionExtensions
{
/// <summary>
/// Adds the <see cref="IStorage" /> service to the service collection.
/// </summary>
public static IServiceCollection AddLocalStorageServices(
this IServiceCollection services) =>
services.AddSingleton<IJSInProcessRuntime>(serviceProvider =>
(IJSInProcessRuntime)serviceProvider.GetRequiredService<IJSRuntime>())
.AddSingleton<IStorage, LocalStorage>();
}
Putting this all together, the Blazor.LocalStorage.WebAssembly
NuGet package is actually only 20 lines of code, and it generates full DI-ready services with JavaScript interop.
Full Changelog: 1.1.1...1.2.0
v1.1.1 Support properties
Add support for properties, for example; localStorage.length
and "eval"
.
Full Changelog: 1.1.0...1.1.1
Release 1.1.0
- Fix generated indentation.
- Added generic support
- Added serialization overload and support
Full Changelog: 1.0.5...1.1.0
Build v1.0.5
Fix issues introduced in 1.0.4
Full Changelog: 1.0.4...1.0.5
Build v1.0.4
Introduced the JSAutoGenericInterop
which allows for API method descriptors, that specify which APIs should be generic instead of string based. This relies on the default JSON serialization native to Blazor JavaScript interop.
Full Changelog: 1.0.3...1.0.4
Build v1.0.3
Full Changelog: 1.0.2...1.0.3
Version 1.0.2
1.0.1
Full Changelog: 1.0.0...1.0.1
Initial bits... let's go! v1
What's Changed
- Github CodeSpaces support by @WeihanLi in #3
- docs: add WeihanLi as a contributor for code by @allcontributors in #4
- docs: add IEvangelist as a contributor for code, design, review, ideas, test by @allcontributors in #5
- Refine the generator by @WeihanLi in #6
- Apply file-scoped namespace style and skip none partial classes by @WeihanLi in #7
New Contributors
- @WeihanLi made their first contribution in #3
- @allcontributors made their first contribution in #4
Full Changelog: https://github.com/IEvangelist/blazorators/commits/1.0.0