Skip to content

Generate DI registrations using implemented interfaces - #84

Open
Denny09310 wants to merge 3 commits into
jscarle:developfrom
Denny09310:develop
Open

Denny09310 wants to merge 3 commits into
jscarle:developfrom
Denny09310:develop

Conversation

@Denny09310

@Denny09310 Denny09310 commented Sep 3, 2026 •

Copy link
Copy Markdown

First of all, big thanks to for creating and maintaining this project. This change builds on that foundation to make interface-based service registration a little more convenient.

Motivation

Blazor Web Apps with interactive render modes, particularly Auto and WebAssembly, can require additional boilerplate when a service has different implementations depending on where it executes.

During SSR, the service executes on the server, while in WebAssembly it executes on the client. When using an interface as the abstraction for the service, the server implementation currently has to be registered separately using the appropriate interface-to-implementation mapping.

This change allows that registration to be generated automatically when the endpoint handler implements an interface.

What this enables

Given an interface:

public interface IWeatherService
{
    Task<WeatherForecast[]> GetForecasts();
}

and a server-side implementation:

public sealed class WeatherService : IWeatherService
{
    // Server implementation
}

the generator can now produce:

services.TryAddScoped<IWeatherService, WeatherService>();

instead of requiring the concrete implementation to be registered separately:

services.TryAddScoped<WeatherService>();

The generated endpoint handler also resolves the handler through the interface:

static ([FromServices] IWeatherService handler) => handler.GetForecasts()

This allows the same abstraction to be used by application code while avoiding additional manual DI registration boilerplate on the server.

This is complementary to approaches such as Refit, where a client-side implementation can be generated from an interface. The purpose of this change is not to provide a shared-contract mechanism itself, but to reduce the boilerplate required when an interface-backed service is used in this kind of architecture.

Implementation

The generator now detects whether the endpoint method is implemented through an interface.

When an applicable interface is found, the generated DI registration becomes:

services.TryAddScoped<IWeatherService, WeatherService>();

and the generated endpoint handler resolves the service through that interface.

When no applicable interface exists, the existing concrete-type registration behavior is preserved:

services.TryAddScoped<WeatherService>();

Result

This keeps endpoint and DI registration automatic while reducing the amount of manual service-registration boilerplate required for interface-based services in Blazor Web Apps with different render modes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant