Orbitra.DependencyInjection.Microsoft
1.0.0
dotnet add package Orbitra.DependencyInjection.Microsoft --version 1.0.0
NuGet\Install-Package Orbitra.DependencyInjection.Microsoft -Version 1.0.0
<PackageReference Include="Orbitra.DependencyInjection.Microsoft" Version="1.0.0" />
<PackageVersion Include="Orbitra.DependencyInjection.Microsoft" Version="1.0.0" />
<PackageReference Include="Orbitra.DependencyInjection.Microsoft" />
paket add Orbitra.DependencyInjection.Microsoft --version 1.0.0
#r "nuget: Orbitra.DependencyInjection.Microsoft, 1.0.0"
#:package Orbitra.DependencyInjection.Microsoft@1.0.0
#addin nuget:?package=Orbitra.DependencyInjection.Microsoft&version=1.0.0
#tool nuget:?package=Orbitra.DependencyInjection.Microsoft&version=1.0.0
Orbitra.DependencyInjection.Microsoft
Orbitra.DependencyInjection.Microsoft provides a first-class adapter between Orbitra (Core) and Microsoft.Extensions.DependencyInjection (IServiceCollection).
It bundles the Core dispatcher & pipeline engine and runtime abstractions so you can wire Orbitra with one line into ASP.NET Core
This package includes:
- Orbitra (Core) — dispatcher + pipeline engine
- Orbitra.Abstractions — request, handler, pipeline, and dispatcher contracts
What this package adds
- Source-generated DI extensions for
IServiceCollection:AddDispatcher()→ registersIDispatcher, pipeline registry, and returns aIDispatcherConfiguratorAddHandlers(TypeLifetime?)→ auto-registers discovered request handlers
- Fluent pipeline builder on top of the Core engine
- A minimal IServiceCollection adapter that binds open-generic pipeline behaviours with the requested lifetime
Install
dotnet add package Orbitra.DependencyInjection.Microsoft
You do not need to install Orbitra.Core or Orbitra.Abstractions separately — they’re included transitively.
Typical usage
using Orbitra.Abstractions.Dispatching;
using Orbitra.Abstractions.Requests;
using Orbitra.DependencyInjection.Microsoft.Generated; // generator adds the DI extensions
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddDispatcher() // IDispatcher + PipelineBehaviourRegistry
.AddHandlers(); // discovered handlers (default: Transient)
var app = builder.Build();
app.MapGet("/users/{id:int}", async (int id, IDispatcher dispatcher, CancellationToken ct) =>
{
return await dispatcher.DispatchAsync(new GetUserQuery(id), ct);
});
app.MapPost("/users", async (CreateUserCommand cmd, IDispatcher dispatcher, CancellationToken ct) =>
{
return await dispatcher.DispatchAsync(cmd, ct);
});
app.Run();
// Example request/handler contracts live in Orbitra.Abstractions
public sealed record GetUserQuery(int Id) : IQuery<UserDto>;
public sealed record UserDto(int Id, string Name);
internal sealed class GetUserQueryHandler : IQueryHandler<GetUserQuery, UserDto>
{
public Task<UserDto> HandleAsync(GetUserQuery req, CancellationToken token = default)
{
return Task.FromResult(new UserDto(req.Id, "Alice"));
}
}
public sealed record CreateUserCommand(string UserName) : ICommand<string>;
internal sealed class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, string>
{
public Task<string> HandleAsync(CreateUserCommand cmd, CancellationToken token = default)
{
return Task.FromResult($"User {cmd.UserName} created!");
}
}
Handler lifetime control
Global default (overrides the generator’s default):
// Register all handlers as Scoped, unless a handler class has [HandlerLifetime(...)]
builder.Services
.AddDispatcher()
.AddHandlers(TypeLifetime.Scoped);
Per-handler override with attribute:
using Microsoft.Extensions.DependencyInjection;
using Orbitra.Core;
// Will override global default TypeLifetime
[HandlerLifetime(TypeLifetime.Singleton)]
internal sealed class CreateUserCommandHandler
: ICommandHandler<CreateUserCommand, string>
{
public Task<string> HandleAsync(CreateUserCommand cmd, CancellationToken token = default)
{
return Task.FromResult($"User {cmd.UserName} created!");
}
}
Pipelines (cross-cutting behaviours)
Define once, then target where and when they run via the fluent builder API.
Behaviour example
public sealed class LoggingBehaviour<TRequest, TResult>
: IPipelineBehaviour<TRequest, TResult>
where TRequest : IRequest<TResult>
{
public async Task<TResult> HandleAsync(
TRequest request,
DispatchHandlerDelegate<TResult> next,
CancellationToken token = default)
{
Console.WriteLine($"Handling {typeof(TRequest).Name}");
var result = await next();
Console.WriteLine($"Handled {typeof(TRequest).Name}");
return result;
}
}
Common recipes
Cache queries only when feature flag is on:
builder.Services
.AddDispatcher()
.AddHandlers()
.AddPipelineBehaviour(typeof(QueryCachingBehaviour<,>))
.EnabledWhen(_ => FeatureFlags.CachingEnabled);
.IncludeQueries()
Metrics everywhere except health checks:
builder.Services
.AddDispatcher()
.AddHandlers()
.AddPipelineBehaviour(typeof(MetricsBehaviour<,>))
.UnlessRequestIs<GetServiceHealthQuery>();
Audit commands; during incidents audit everything (OtherwiseAll fallback):
builder.Services
.AddDispatcher()
.AddHandlers()
.AddPipelineBehaviour(typeof(AuditBehaviour<,>))
.IncludeCommands()
.When(_ => !Ops.IncidentMode)
.OtherwiseAll();
Rate-limit only heavy report queries:
builder.Services
.AddDispatcher()
.AddHandlers()
.AddPipelineBehaviour(typeof(RateLimitBehaviour<,>))
.WhenRequest<GenerateReportQuery>(static q => q.RangeDays > 7);
Rule primitives
| Rule | Meaning |
|---|---|
EnabledWhen(predicate) |
Enable / disable entire chain. If this is false, nothing in that chain runs regardless of other rules. |
Include<TRequest>() / Include(typeof(...), ...) |
Run only for selected requests |
Exclude<TRequest>() / Exclude(typeof(...), ...) |
Run for all except selected requests |
IncludeCommands() / IncludeQueries() |
Category-based includes |
ExcludeCommands() / ExcludeQueries() |
Category-based excludes |
When(predicate) |
Conditional activation |
Unless(predicate) |
Conditional skip |
And extensions:
| Extension | Use case |
|----------------------|----------|
| WhenRequestIs<T> | Run only for one specific type. |
| WhenRequest<T> | Run only for one type when the predicate is true. |
| UnlessRequestIs<T> | Run for all except this one type. |
| UnlessRequest<T> | Run for all except when request is this type and predicate is true. |
| OtherwiseAll | Fallback to run on everything |
Predicates receive (Type requestType) => bool, (Type requestType, object request, IServiceProvider services) => bool or a simplified _ => bool, and async variances of these as well.
The generated extensions (what the generator emits)
The exact content varies per project; this is representative output.
// <auto-generated/>
#nullable enable
using Microsoft.Extensions.DependencyInjection;
namespace Orbitra.DependencyInjection.Microsoft.Generated;
internal static class ServiceCollectionExtensions
{
public static global::Orbitra.Core.Pipelines.Abstractions.IDispatcherConfigurator AddDispatcher(this IServiceCollection services)
{
services.AddScoped<global::Orbitra.Abstractions.Dispatching.IDispatcher, global::Orbitra.Generated.Dispatcher>();
var registry = new global::Orbitra.Core.Pipelines.PipelineBehaviourRegistry();
services.AddSingleton<global::Orbitra.Core.Pipelines.Abstractions.IPipelineBehaviourRegistry>(registry);
return new global::Orbitra.Core.Pipelines.Builders.DispatcherConfigurator(
new global::Orbitra.DependencyInjection.Microsoft.MsDiServiceRegistrator(services),
registry
);
}
public static global::Orbitra.Core.Pipelines.Abstractions.IDispatcherConfigurator AddHandlers(
this global::Orbitra.Core.Pipelines.Abstractions.IDispatcherConfigurator builder,
global::Orbitra.Core.TypeLifetime typeLifetime = global::Orbitra.Core.TypeLifetime.Transient)
{
// Example registrations; the generator emits your project’s concrete handlers:
// builder.Services.Add<IRequestHandler<CreateUserCommand, string>, CreateUserCommandHandler>(typeLifetime);
// builder.Services.Add<IRequestHandler<GetUserQuery, UserModel>, GetUserQueryHandler>(typeLifetime);
return builder;
}
}
Under the hood: the IServiceCollection adapter
The adapter binds open generic behaviour families (e.g., IPipelineBehaviour<,>) with the requested lifetime:
using Microsoft.Extensions.DependencyInjection;
using Orbitra.Core;
using Orbitra.Core.Pipelines.Abstractions;
namespace Orbitra.DependencyInjection.Microsoft;
public sealed class MsDiServiceRegistrator(IServiceCollection services) : IServiceRegistrator
{
public void AddOpenGeneric(Type serviceOpenGeneric, Type implementation, TypeLifetime lifetime)
{
services.Add(new ServiceDescriptor(serviceOpenGeneric, implementation, MapLifetime(lifetime)));
}
private static ServiceLifetime MapLifetime(TypeLifetime lifetime)
{
return lifetime switch
{
TypeLifetime.Scoped => ServiceLifetime.Scoped,
TypeLifetime.Transient => ServiceLifetime.Transient,
TypeLifetime.Singleton => ServiceLifetime.Singleton,
_ => ServiceLifetime.Singleton
};
}
}
This is all that’s needed to bridge Orbitra’s Core pipeline engine with Microsoft’s DI container.
Related Packages
| Package | Description |
|---|---|
| Orbitra | The runtime dispatcher and pipeline engine. Required for actual dispatching and pipeline execution. |
| Orbitra.Abstractions | Lightweight runtime contracts for requests, handlers, and pipeline behaviours |
License
Code © 2025 Robin Hörnkvist
Licensed under Apache License 2.0 — see LICENSE
Third-party notices — see NOTICE
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
- Orbitra (>= 1.0.0)
-
net9.0
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
- Orbitra (>= 1.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 159 | 10/31/2025 |