Skip to content

Dependency Injection

samgerene edited this page Oct 4, 2026 · 4 revisions

Dependency Injection

ArgusTransfer integrates with Microsoft.Extensions.DependencyInjection through a set of extension methods on IServiceCollection.

Extension Methods

AddArgusModules

services.AddArgusModules();
services.AddArgusModules(typeof(MyModule).Assembly, typeof(OtherModule).Assembly);

Scans assemblies for all classes implementing IArgusModule, registers each as a transient service, and registers ArgusRouter as a singleton. The router automatically calls AddRoutes on each discovered module during construction.

  • Without arguments, the calling assembly is scanned: the assembly whose code calls AddArgusModules(). The method is never inlined, so this holds in Release builds too.
  • With assemblies, exactly the specified assemblies are scanned. Use this when the modules live in a different assembly than the code that registers them. Passing no assemblies or a null assembly throws ArgumentException.

Both overloads can be called several times and combined. Each module type and the router are registered only once.

AddArgusPipeHost

services.AddArgusPipeHost();
services.AddArgusPipeHost(options => { options.PipeName = "myservice"; });

Registers ArgusPipeHostBackgroundService as a hosted service (singleton lifetime). Automatically calls AddArgusPlainTextProtocol() to register the default body serializer. The optional Action<ArgusPipeHostOptions> configures the server -- see Server Configuration for all options.

AddArgusClient

services.AddArgusClient("mypipe");
services.AddArgusClient("mypipe", TimeSpan.FromSeconds(60));

Registers IArgusClient as a transient service backed by ArgusClient. If an IArgusBodySerializerRegistry is available in the container, the client uses it automatically. See Client Usage for details.

An overload adds automatic retries of transient pipe failures:

services.AddArgusClient("mypipe", TimeSpan.FromSeconds(60), retry =>
{
    retry.MaxRetries = 3;
    retry.Strategy = RetryBackoffStrategy.Exponential;
});

To configure each created client directly -- timeout, retry policy, compression -- use the overload that takes an Action<ArgusClient>:

services.AddArgusClient("mypipe", client =>
{
    client.DefaultTimeout = TimeSpan.FromSeconds(60);
    client.Compression.Enabled = true;
});

For the retry overload, the action receives an ArgusRetryPolicy with its defaults already set; passing null leaves retries disabled. This overload also gives the client an ILogger<ArgusClient> when logging is registered, so each retry is logged as a warning. See Automatic Retries.

AddArgusExceptionHandler

services.AddArgusExceptionHandler();
services.AddArgusExceptionHandler(options => options.IncludeExceptionDetails = true); // development only

Registers ArgusExceptionHandlerMiddleware as a singleton. The router created by AddArgusModules() adds it as the outermost global middleware, regardless of call order. See Middleware.

AddArgusAuthentication<THandler>

services.AddArgusAuthentication<ApiKeyHandler>();
services.AddArgusAuthentication<ApiKeyHandler>(options => options.RequireAuthentication = false);

Registers THandler as the singleton IArgusAuthenticationHandler (the first registration wins) and ArgusAuthenticationMiddleware as a singleton. The router adds the middleware right after the exception handler and before any module middleware. See Authentication.

AddArgusPlainTextProtocol

services.AddArgusPlainTextProtocol();

Registers PlainTextArgusBodySerializer as a singleton and adds it to the IArgusBodySerializer enumerable. Registers ArgusBodySerializerRegistry as the IArgusBodySerializerRegistry singleton. This method is called automatically by AddArgusPipeHost().

AddArgusBodySerializer<T>

services.AddArgusBodySerializer<JsonArgusBodySerializer>(); // your own IArgusBodySerializer implementation

Registers an additional IArgusBodySerializer implementation. Uses TryAddEnumerable to avoid duplicate registrations. See Serialization for writing custom serializers.

Recommended Registration Order

Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddArgusModules();                            // 1. Discover modules and build router
        services.AddArgusExceptionHandler();                   // 2. Structured 500s (optional)
        services.AddArgusAuthentication<ApiKeyHandler>();      // 3. Authentication (optional)
        services.AddArgusPipeHost(o => o.PipeName = "sample"); // 4. Register server (includes plain text protocol)
        services.AddArgusClient("sample");                     // 5. Register client (optional)
        services.AddArgusBodySerializer<MySerializer>();        // 6. Add custom serializers (optional)
    })
    .Build()
    .Run();

Service Lifetimes

Service Lifetime Registered By
IArgusModule implementations Transient AddArgusModules()
ArgusRouter Singleton AddArgusModules()
ArgusPipeHostBackgroundService Singleton (Hosted Service) AddArgusPipeHost()
IArgusClient / ArgusClient Transient AddArgusClient()
ArgusExceptionHandlerMiddleware Singleton AddArgusExceptionHandler()
IArgusAuthenticationHandler Singleton AddArgusAuthentication<THandler>()
ArgusAuthenticationMiddleware Singleton AddArgusAuthentication<THandler>()
PlainTextArgusBodySerializer Singleton AddArgusPlainTextProtocol()
IArgusBodySerializerRegistry Singleton AddArgusPlainTextProtocol()
Custom IArgusBodySerializer Per implementation AddArgusBodySerializer<T>()

Using RequestServices in Handlers

The ArgusContext.RequestServices property provides access to the DI container from within route handlers:

app.MapGet("/items", context =>
{
    var myService = context.RequestServices.GetRequiredService<IMyService>();

    var result = myService.GetItems();

    context.Response = new ArgusResponse
    {
        StatusCode = ArgusStatusCode.Ok,
        Body = JsonSerializer.Serialize(result)
    };

    return Task.CompletedTask;
});

Clone this wiki locally