SkillAgentSearch skills...

Blazorators

This project converts TypeScript type declarations into C# representations, and use C# source generators to expose automatic JavaScript interop functionality.

Install / Use

/learn @IEvangelist/Blazorators

README

<img src="https://raw.githubusercontent.com/IEvangelist/blazorators/main/logo.png" align="right"></img>

Blazorators: Blazor C# Source Generators

Thank you for perusing my Blazor C# Source Generator repository. I'd really appreciate a ⭐ if you find this interesting.

build

<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->

All Contributors

<!-- ALL-CONTRIBUTORS-BADGE:END --> <!-- ## Stats ![Alt](https://repobeats.axiom.co/api/embed/6d5b98efd6598a4482f1fa6391fbe651a06f77d9.svg "Repobeats analytics image") -->

A C# source generator that creates fully functioning Blazor JavaScript interop code, targeting either the IJSInProcessRuntime or IJSRuntime types. This library provides several NuGet packages:

Core libraries

| NuGet package | NuGet version | Description | |--|--|--| | Blazor.SourceGenerators | NuGet | Core source generator library. | | Blazor.Serialization | NuGet | Common serialization library, required in some scenarios when using generics. |

WebAssembly libraries

| NuGet package | NuGet version | Description | |--|--|--| | Blazor.LocalStorage.WebAssembly | NuGet | Blazor WebAssembly class library exposing DI-ready IStorageService type for the localStorage implementation (relies on IJSInProcessRuntime). | | Blazor.SessionStorage.WebAssembly | NuGet | Blazor WebAssembly class library exposing DI-ready IStorageService type for the sessionStorage implementation (relies on IJSInProcessRuntime). | | Blazor.Geolocation.WebAssembly | NuGet | Razor class library exposing DI-ready IGeolocationService type (and dependent callback types) for the geolocation implementation (relies on IJSInProcessRuntime). | | Blazor.SpeechSynthesis.WebAssembly | NuGet | Razor class library exposing DI-ready ISpeechSynthesisService type for the speechSynthesis implementation (relies on IJSInProcessRuntime). |

Targets the IJSInProcessRuntime type.

Server libraries

| NuGet package | NuGet version | Description | |--|--|--| | Blazor.LocalStorage | NuGet | Blazor Server class library exposing DI-ready IStorageService type for the localStorage implementation (relies on IJSRuntime) | | Blazor.SessionStorage | NuGet | Blazor Server class library exposing DI-ready IStorageService type for the sessionStorage implementation (relies on IJSRuntime) | | Blazor.Geolocation | NuGet | Razor class library exposing DI-ready IGeolocationService type (and dependent callback types) for the geolocation implementation (relies on IJSRuntime). | | Blazor.SpeechSynthesis | NuGet | Razor class library exposing DI-ready ISpeechSynthesisService type for the speechSynthesis implementation (relies on IJSRuntime). |

Targets the IJSRuntime type.

Note<br> The reason that I generate two separate packages, one with an async API and another with the synchronous version is due to the explicit usage of IJSInProcessRuntime when using Blazor WebAssembly. This decision allows the APIs to be separate, and easily consumable from their repsective consuming Blazor apps, either Blazor server or Blazor WebAssembly. I might change it later to make this a consumer configuration, in that each consuming library will have to explicitly define a preprocessor directive to specify IS_WEB_ASSEMBLY defined.

Using the Blazor.SourceGenerators package 📦

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 IStorageService.cs C# file:

// Copyright (c) David Pine. All rights reserved.
// Licensed under the MIT License.

namespace Microsoft.JSInterop;

[JSAutoGenericInterop(
    TypeName = "Storage",
    Implementation = "window.localStorage",
    Url = "https://developer.mozilla.org/docs/Web/API/Window/localStorage",
    GenericMethodDescriptors = new[]
    {
        "getItem",
        "setItem:value"
    })]
public partial interface IStorageService
{
}

This code designates itself into the Microsoft.JSInterop namespace, making the source generated implementation available to anyone consumer who uses types from this namespace. It uses the JSAutoGenericInterop to specify:

  • TypeName = "Storage": sets the type to Storage.
  • Implementation = "window.localStorage": expresses how to locate the implementation of the specified type from the globally scoped window object, this is the localStorage implementation.
  • Url: sets the URL for the implementation.
  • GenericMethodDescriptors: Defines the methods that should support generics as part of their source-generation. The localStorage.getItem is specified to return a generic TResult type, and the localStorage.setItem has its parameter with a name of value specified as a generic TArg 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 interface and it needs to be partial, for example; public partial interface. Decorating the class with the JSAutoInterop (or `JSAutoGenericInterop) attribute will source generate the following C# code, as shown in the source generated IStorageServiceService.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 partial interface IStorageServiceService
{
    /// <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;
    }

    /// <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>
    TValue? GetItem<TValue>(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<TValue>(string key, TValue value, JsonSerializerOptions? options = null);
}

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:

View on GitHub
GitHub Stars385
CategoryDevelopment
Updated2d ago
Forks32

Languages

C#

Security Score

100/100

Audited on Mar 30, 2026

No findings