Class BowireServiceCollectionExtensions

Namespace
Kuestenlogik.Bowire
Assembly
Kuestenlogik.Bowire.dll

DI-container extensions that wire Bowire and its installed protocol plugins into an ASP.NET application.

public static class BowireServiceCollectionExtensions
Inheritance
BowireServiceCollectionExtensions
Inherited Members

Remarks

Paired with MapBowire(IEndpointRouteBuilder, string, Action<BowireOptions>?): call AddBowire() in Program.cs before builder.Build(), then MapBowire() on the resulting app.

Methods

AddBowire(IServiceCollection)

Registers Bowire and auto-configures the DI prerequisites for every installed protocol plugin.

public static IServiceCollection AddBowire(this IServiceCollection services)

Parameters

services IServiceCollection

The application's service collection.

Returns

IServiceCollection

The same services instance, so calls can be chained (for example with .AddBowire().AddAuthentication(…)).

Examples

Without AddBowire, protocols must be configured by hand:

builder.Services.AddGrpc();
builder.Services.AddGrpcReflection();
// ... and every other protocol's own setup ...
var app = builder.Build();
app.MapGrpcReflectionService();
app.MapBowire();

With AddBowire, a single line covers every referenced plugin:

builder.Services.AddBowire();
var app = builder.Build();
app.MapBowire();

Remarks

Scans every loaded assembly whose name starts with Kuestenlogik.Bowire for types that implement IBowireProtocolServices and invokes ConfigureServices(IServiceCollection) on each. Only protocols whose NuGet package is actually referenced by the host project are activated — no gRPC reference means no gRPC Server Reflection is registered, no SignalR reference means no hub enumeration, and so on.

A preliminary pass force-loads every Kuestenlogik.Bowire*.dll from the application's output directory so that plugins shipped as runtime dependencies (but not touched by the CLR yet) are discovered too. Assemblies that fail to enumerate types are silently skipped to keep startup resilient in misconfigured deployments.

See Also

AddBowire(IServiceCollection, Action<BowireOptions>?)

Overload that exposes a configuration callback for the subset of BowireOptions that needs to be settled at AddServices time rather than at MapBowire(IEndpointRouteBuilder, string, Action<BowireOptions>?) time. Today the only such option is SchemaHintsPath — the user-local schema-hints file path that the LayeredAnnotationStore singleton needs at construction. Everything else still flows through the regular MapBowire callback.

public static IServiceCollection AddBowire(this IServiceCollection services, Action<BowireOptions>? configure)

Parameters

services IServiceCollection
configure Action<BowireOptions>

Returns

IServiceCollection

AddBowireEnvironment(IServiceCollection, string, Action<BowireProvisionedEnvironment>)

Declare an environment from the host's own configuration (#49).

public static IServiceCollection AddBowireEnvironment(this IServiceCollection services, string name, Action<BowireProvisionedEnvironment> configure)

Parameters

services IServiceCollection

The host's container.

name string

What it is called in the workbench's switcher.

configure Action<BowireProvisionedEnvironment>

Fills in the variables.

Returns

IServiceCollection

Examples

services.AddBowire();
services.AddBowireEnvironment("Staging", env => env
    .Set("baseUrl", configuration["Api:BaseUrl"])
    .Set("tenant", options.Value.TenantId));

Remarks

An embedded host already knows its base URLs and tenant ids; without this the only way to use them in the workbench was to read them out of appsettings.json and type them in again, leaving two copies of which one goes quietly wrong the moment the other changes.

Declared environments are contributed on every start and never written to environments.json. Change the host's configuration, restart, and the environment changes with it — nothing stale left behind, and nothing for the workbench to save back and end up holding twice.

Call it once per environment. A second call with the same name replaces the first, so a host composing configuration in layers gets the last word rather than two entries sharing a name.

AddBowireModule<TModule>(IServiceCollection)

Counterpart to AddBowireRail<TRail>(IServiceCollection) for cross-cutting modules (AI, Assistant, var-resolver, …).

public static IServiceCollection AddBowireModule<TModule>(this IServiceCollection services) where TModule : class, IBowireModuleContribution, new()

Parameters

services IServiceCollection

Returns

IServiceCollection

Type Parameters

TModule

AddBowirePlugins(IServiceCollection, IConfiguration)

Overload that reads the plugin directory from a bound IConfiguration. Looks at Bowire:PluginDir; returns unchanged when the key is unset so callers can wire this into their startup pipeline unconditionally.

public static IServiceCollection AddBowirePlugins(this IServiceCollection services, IConfiguration configuration)

Parameters

services IServiceCollection
configuration IConfiguration

Returns

IServiceCollection

Remarks

This is the preferred wiring for embedded hosts that already build an IConfiguration from appsettings.json or similar:

builder.Services
       .AddBowirePlugins(builder.Configuration)
       .AddBowire();

Plugins themselves read their own config section via the standard .NET options pattern:

public void ConfigureServices(IServiceCollection services)
{
    services.AddOptions<MyPluginOptions>()
            .BindConfiguration("Bowire:Plugins:MyPlugin");
}

AddBowirePlugins(IServiceCollection, string)

Load every .dll under pluginDir into the default AssemblyLoadContext so the subsequent AddBowire(IServiceCollection) reflection pass picks the plugins up. Intended for embedded hosts that want to extend the workbench with out-of-tree protocol plugins without depending on the bowire CLI tool.

public static IServiceCollection AddBowirePlugins(this IServiceCollection services, string pluginDir)

Parameters

services IServiceCollection

The application's service collection (returned unchanged, for chaining).

pluginDir string

Directory to scan. Per-package subdirectories (pluginDir/<package>/*.dll) are the primary layout — matches what bowire plugin install produces — but loose DLLs at the top level are picked up too.

Returns

IServiceCollection

Remarks

Non-existent paths are treated as empty (no throw) so callers can blindly pass a configured directory even when no plugins have been installed yet. DLLs that fail to load are silently skipped — the equivalent behaviour to the bowire CLI's plugin loader. Call this before AddBowire(IServiceCollection).

AddBowireRail<TRail>(IServiceCollection)

Register a specific rail contribution explicitly (in addition to the auto-discovery pass driven by AddBowire(IServiceCollection)). Useful when (a) the host wants to override a built-in rail's metadata without forking the contributing package, or (b) the rail descriptor lives in an assembly that isn't loaded by the auto-scan reach.

public static IServiceCollection AddBowireRail<TRail>(this IServiceCollection services) where TRail : class, IBowireRailContribution, new()

Parameters

services IServiceCollection

Returns

IServiceCollection

Type Parameters

TRail

Rail contribution type. Must implement IBowireRailContribution and expose a parameterless constructor — the registry instantiates the descriptor without passing dependencies (it's a metadata object).