Skip to content

Chrison-dev/Scrutor.Extensions.HttpClient

Repository files navigation

Scrutor.Extensions.HttpClient

NuGet Downloads Build & Test Built with Fallout License

A tiny companion for Scrutor that lets its assembly-scanning register each matched class as a typed HttpClient (via IHttpClientFactory) instead of a plain service — the one thing Scrutor deliberately doesn't do out of the box.

services.Scan(scan => scan
    .FromAssemblyOf<IWeatherClient>()
    .AddClasses(c => c.AssignableTo<IApiClient>())
    .AsMatchingInterface()
    .AsHttpClient("weather"));   // ← every scanned client becomes a typed HttpClient

Install

dotnet add package Scrutor.Extensions.HttpClient

Usage

  1. Register a named HttpClient with your shared configuration.
  2. Make your API clients implement a common marker interface (and, for .AsMatchingInterface(), an I{ClassName} interface each).
  3. Scan for them and finish the chain with .AsHttpClient("<name>").
// 1. A named client carrying the shared config (base address, handlers, Polly, …).
services.AddHttpClient("weather", client =>
{
    client.BaseAddress = new Uri("https://api.example.com");
});

// 2 + 3. Register every IApiClient implementation as a typed client of "weather".
services.Scan(scan => scan
    .FromAssemblyOf<IWeatherClient>()
    .AddClasses(classes => classes.AssignableTo<IApiClient>())
    .AsMatchingInterface()
    .AsHttpClient("weather"));

Now each scanned client is resolved from IHttpClientFactory with the "weather" client's configuration injected:

public sealed class WeatherClient(HttpClient http) : IWeatherClient
{
    public Task<Forecast?> GetAsync(string city) =>
        http.GetFromJsonAsync<Forecast>($"forecast/{city}");
}

Overloads

Call Behaviour
.AsHttpClient("name") Registers each scanned class as a typed client bound to the named client "name" — they share its configuration.
.AsHttpClient() Registers each scanned class as a typed client with its own default client (named after the service type).

Both are IServiceTypeSelector extensions, so they slot onto the end of any Scrutor .Scan(...) chain (.AsMatchingInterface(), .AsSelf(), .As<T>(), …).

Compatibility

  • Scrutor 7.x — the package major tracks Scrutor's major (7.x ↔ Scrutor 7.x).
  • Targets net8.0 and netstandard2.0 (so it's usable from .NET Framework 4.6.2+, .NET Core 2.0+, and modern .NET alike).

Trimming / AOT

This bridges Scrutor's runtime assembly scan and closes the generic AddHttpClient<TClient,TImplementation> over the scanned types via reflection, so it is not trim- or Native-AOT-safe. The public methods are annotated with [RequiresUnreferencedCode] / [RequiresDynamicCode], so a trimmed/AOT build gets an honest warning at the call site rather than silent breakage.

Building

CI is defined in C# with Fallout (a NUKE fork); the GitHub Actions workflow is generated from the build, never hand-edited.

./build.cmd Test    # run the spec suite
./build.cmd Pack    # test + pack the NuGet package

License

MIT

About

Scrutor extension that registers assembly-scanned classes as typed HttpClients (IHttpClientFactory). Solves khellang/Scrutor#180.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages