Skip to content

TieredProviderSelectorServiceCollectionExtensions

NexusLabs.Needlr.AgentFramework

NexusLabs.Needlr.AgentFramework.Providers

TieredProviderSelectorServiceCollectionExtensions Class

Extension methods that register an ITieredProviderSelector<TQuery,TResult> with optional consumer-supplied TieredProviderSelectorOptions in the DI container.

public static class TieredProviderSelectorServiceCollectionExtensions

Inheritance System.Object 🡒 TieredProviderSelectorServiceCollectionExtensions

Remarks

Wraps the boilerplate of resolving providers, the quota gate, the execution-context accessor, and System.TimeProvider from the container so consumers do not have to hand-roll the same factory in every host.

Registration semantics: last-wins (override-friendly). The extension uses AddSingleton (not TryAddSingleton). If the same (TQuery, TResult) pair is registered multiple times — for example, by two plugins — System.IServiceProvider.GetService(System.Type) resolves the LAST descriptor added. This is the intentional convention for consumer-supplied configuration: a downstream plugin or test harness can override an upstream plugin's selector registration without removing it first. (The System.TimeProvider dependency is registered with TryAddSingleton because it IS framework infrastructure — first-wins is correct for that.)

Lifetime: Singleton. The selector's per-instance skip cache is the whole point of registering it as a long-lived service — registering as Scoped would reset the cache per request, defeating the purpose. If you need a different lifetime, hand-roll the registration.

Configure delegate evaluation. Both configure overloads invoke the supplied delegate INSIDE the singleton factory at first resolution, with a real System.IServiceProvider in scope. This means OnHit callbacks can resolve other services (loggers, options monitors, telemetry sinks) from the container — register them BEFORE calling ITieredProviderSelector<TQuery,TResult>.GetRequiredService for the first time. The delegate runs exactly once per Singleton lifetime; throw an System.InvalidOperationException if it returns null.

Methods

TieredProviderSelectorServiceCollectionExtensions.AddTieredProviderSelector<TQuery,TResult>(this IServiceCollection) Method

Registers an ITieredProviderSelector<TQuery,TResult> as a singleton using Default (PUE-only fall-through, no skip, no callback).

public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTieredProviderSelector<TQuery,TResult>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services);

Type parameters

TQuery

Query type for the selector.

TResult

Result type for the selector.

Parameters

services Microsoft.Extensions.DependencyInjection.IServiceCollection

Service collection to add the registration to.

Returns

Microsoft.Extensions.DependencyInjection.IServiceCollection
The same services instance for chaining.

Exceptions

System.ArgumentNullException
services is null.

TieredProviderSelectorServiceCollectionExtensions.AddTieredProviderSelector<TQuery,TResult>(this IServiceCollection, Func<TieredProviderSelectorOptions,TieredProviderSelectorOptions>) Method

Registers an ITieredProviderSelector<TQuery,TResult> as a singleton with consumer-supplied options derived from Default.

public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTieredProviderSelector<TQuery,TResult>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func<NexusLabs.Needlr.AgentFramework.Providers.TieredProviderSelectorOptions,NexusLabs.Needlr.AgentFramework.Providers.TieredProviderSelectorOptions> configure);

Type parameters

TQuery

Query type for the selector.

TResult

Result type for the selector.

Parameters

services Microsoft.Extensions.DependencyInjection.IServiceCollection

Service collection to add the registration to.

configure System.Func<TieredProviderSelectorOptions,TieredProviderSelectorOptions>

Delegate that receives Default and returns the (possibly mutated) options to use. Runs lazily inside the singleton factory at first resolution. Must not return null.

Returns

Microsoft.Extensions.DependencyInjection.IServiceCollection
The same services instance for chaining.

Exceptions

System.ArgumentNullException
services or configure is null.

Remarks

Use this overload when your OnHit callbacks (and any other policy fields) do not need access to other DI services. If you need an ILogger, IOptionsMonitor, or any other container-resolved service inside your callbacks, use the AddTieredProviderSelector<TQuery,TResult>(this IServiceCollection, Func<IServiceProvider,TieredProviderSelectorOptions,TieredProviderSelectorOptions>) overload instead.

TieredProviderSelectorServiceCollectionExtensions.AddTieredProviderSelector<TQuery,TResult>(this IServiceCollection, Func<IServiceProvider,TieredProviderSelectorOptions,TieredProviderSelectorOptions>) Method

Registers an ITieredProviderSelector<TQuery,TResult> as a singleton with consumer-supplied options derived from Default, with access to the System.IServiceProvider so policy callbacks can resolve other container services.

public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTieredProviderSelector<TQuery,TResult>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func<System.IServiceProvider,NexusLabs.Needlr.AgentFramework.Providers.TieredProviderSelectorOptions,NexusLabs.Needlr.AgentFramework.Providers.TieredProviderSelectorOptions> configure);

Type parameters

TQuery

Query type for the selector.

TResult

Result type for the selector.

Parameters

services Microsoft.Extensions.DependencyInjection.IServiceCollection

Service collection to add the registration to.

configure System.Func<System.IServiceProvider,TieredProviderSelectorOptions,TieredProviderSelectorOptions>

Delegate that receives the System.IServiceProvider and Default and returns the (possibly mutated) options to use. Runs lazily inside the singleton factory at first resolution. Must not return null.

Returns

Microsoft.Extensions.DependencyInjection.IServiceCollection
The same services instance for chaining.

Exceptions

System.ArgumentNullException
services or configure is null.

Example

services.AddTieredProviderSelector<WebSearchQuery, IReadOnlyList<WebSearchResult>>(
    (sp, opts) =>
    {
        var logger = sp.GetRequiredService<ILogger<CopilotWebSearchProvider>>();
        return opts with
        {
            FailurePolicies =
            [
                .. opts.FailurePolicies,
                new ProviderFailurePolicy(
                    Match: ex => ex is CopilotAuthException,
                    SkipDuration: TimeSpan.FromMinutes(5),
                    OnHit: ctx =>
                    {
                        logger.LogWarning(ctx.Exception,
                            "Provider {Provider} skipped until {Until}",
                            ctx.ProviderName, ctx.SkipUntil);
                        return ValueTask.CompletedTask;
                    }),
            ],
        };
    });