Releases: IEvangelist/blazorators
1.4.4
Test Colin's better workflow
What's Changed
- Refactor workflow for less repetition by @colindembovsky in #12
New Contributors
- @colindembovsky made their first contribution in #12
Full Changelog: 1.4.3...1.4.4
Version 1.4.3
- Source generate overloads to accept
Action<T>
- thanks @stephentoub for the suggestion
Example input
namespace Microsoft.JSInterop;
[JSAutoInterop(
TypeName = "Geolocation",
Implementation = "window.navigator.geolocation",
Url = "https://developer.mozilla.org/docs/Web/API/Geolocation")]
public partial interface IGeolocationService
{
}
Example output
#nullable enable
namespace Microsoft.JSInterop;
/// <summary>
/// Source generated interface definition of the <c>Geolocation</c> type.
/// </summary>
public partial interface IGeolocationService
{
/// <summary>
/// Source generated implementation of <c>window.navigator.geolocation.clearWatch</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Geolocation/clearWatch"></a>
/// </summary>
void ClearWatch(double watchId);
/// <summary>
/// Source generated implementation of <c>window.navigator.geolocation.getCurrentPosition</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Geolocation/getCurrentPosition"></a>
/// </summary>
/// <param name = "component">The calling Razor (or Blazor) component.</param>
/// <param name = "onSuccessCallbackMethodName">Expects the name of a <c>"JSInvokableAttribute"</c> C# method with the following <c>System.Action{GeolocationPosition}"</c>.</param>
/// <param name = "onErrorCallbackMethodName">Expects the name of a <c>"JSInvokableAttribute"</c> C# method with the following <c>System.Action{GeolocationPositionError}"</c>.</param>
/// <param name = "options">The <c>PositionOptions</c> value.</param>
void GetCurrentPosition<TComponent>(
TComponent component,
string onSuccessCallbackMethodName,
string? onErrorCallbackMethodName = null,
PositionOptions? options = null)
where TComponent : class;
/// <summary>
/// Source generated implementation of <c>window.navigator.geolocation.getCurrentPosition</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Geolocation/getCurrentPosition"></a>
/// </summary>
void GetCurrentPosition(
Action<GeolocationPosition> onSuccessCallback,
Action<GeolocationPositionError>? onErrorCallback = null,
PositionOptions? options = null);
/// <summary>
/// Source generated implementation of <c>window.navigator.geolocation.watchPosition</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Geolocation/watchPosition"></a>
/// </summary>
/// <param name = "component">The calling Razor (or Blazor) component.</param>
/// <param name = "onSuccessCallbackMethodName">Expects the name of a <c>"JSInvokableAttribute"</c> C# method with the following <c>System.Action{GeolocationPosition}"</c>.</param>
/// <param name = "onErrorCallbackMethodName">Expects the name of a <c>"JSInvokableAttribute"</c> C# method with the following <c>System.Action{GeolocationPositionError}"</c>.</param>
/// <param name = "options">The <c>PositionOptions</c> value.</param>
double WatchPosition<TComponent>(
TComponent component,
string onSuccessCallbackMethodName, string?
onErrorCallbackMethodName = null,
PositionOptions? options = null)
where TComponent : class;
/// <summary>
/// Source generated implementation of <c>window.navigator.geolocation.watchPosition</c>.
/// <a href="https://developer.mozilla.org/docs/Web/API/Geolocation/watchPosition"></a>
/// </summary>
double WatchPosition(
Action<GeolocationPosition> onSuccessCallback,
Action<GeolocationPositionError>? onErrorCallback = null,
PositionOptions? options = null);
}
Additionally, all of the dependent types are also generated. As well as the dependency injection hooks, and the corresponding implementation.
IGeolocationServices.g.cs
GeolocationServices.g.cs
GeolocationServiceCollectionExtensions.g.cs
GeolocationPosition.g.cs
GeolocationPositionError.g.cs
GeolocationCoordinates.g.cs
PositionOptions.g.cs
Full Changelog: 1.4.2...1.4.3
Release v1.4.2
New libs for session storage
Full Changelog: 1.4.0...1.4.2
Release 1.4.1 - New libs
- Add session storage libs, and introduce Bing maps in example
Full Changelog: 1.4.0...1.4.1
Version 1.4.0
- Target
public partial interface
instead ofinternal static partial class
- More XML comments
- Append
Service
suffix to interface and impls.
Full Changelog: 1.3.3...1.4.0
v1.3.3 (version 1.3.2, but better)
- Implemented Geolocation server-side
- Fixed attributes
- More XML comments
- Better serialization
- Helpers for epoch time and DOMTimeStamp
Full Changelog: 1.3.1...1.3.3
1.3.2
- Implemented Geolocation server-side
- Fixed attributes
- More XML comments
- Better serialization
- Helpers for epoch time and
DOMTimeStamp
Full Changelog: 1.3.1...1.3.2
v1.3.1 bugs
Fix package name
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