Created in Poland by Leszek Pomianowski and open-source community.
Small fluent extensions for registering inline hosted services in .NET dependency injection.
dotnet add package Fluent.Hostinghttps://www.nuget.org/packages/Fluent.Hosting
using Fluent.Hosting;
builder.Services.AddHostedService<IMigrator>(async (migrator, token) =>
{
await migrator.MigrateAsync(token);
});The package registers delegates as IHostedService instances. Use it when a startup or background task is simple enough that a dedicated hosted service class would add noise.
| Method | Provider used by the action | Runs as | Typical use |
|---|---|---|---|
AddHostedService |
Application service provider | IHostedService |
Startup work that should complete before the host finishes starting |
AddScopedHostedService |
New DI scope | IHostedService |
Startup work that needs scoped services, such as database sessions |
AddBackgroundService |
Application service provider | BackgroundService |
Long-running or fire-and-forget background work |
AddScopedBackgroundService |
New DI scope | BackgroundService |
Background work that needs scoped services |
All registrations are singleton IHostedService registrations. Multiple calls add multiple hosted services; each delegate runs.
Use AddHostedService when the delegate can use singleton services or the root service provider directly.
builder.Services.AddHostedService(async (services, token) =>
{
var cache = services.GetRequiredService<IProductCache>();
await cache.WarmAsync(token);
});You can also ask Fluent.Hosting to resolve the service for you:
builder.Services.AddHostedService<IProductCache>(async (cache, token) =>
{
await cache.WarmAsync(token);
});AddHostedService waits for the delegate to complete during host startup.
Use AddScopedHostedService when the work needs scoped dependencies.
builder.Services.AddScopedHostedService<IDocumentSession>(async (session, token) =>
{
session.Store(new MyData());
await session.SaveChangesAsync(token);
});The service creates a scope for the delegate, resolves IDocumentSession from that scope, and disposes the scope after the delegate completes.
Use AddBackgroundService when the delegate should run as a BackgroundService.
builder.Services.AddBackgroundService<IQueueWorker>(async (worker, token) =>
{
await worker.RunAsync(token);
});You can also access the provider directly:
builder.Services.AddBackgroundService(async (services, token) =>
{
var worker = services.GetRequiredService<IQueueWorker>();
await worker.RunAsync(token);
});Use AddScopedBackgroundService when background work needs scoped dependencies.
builder.Services.AddScopedBackgroundService<IDocumentSession>(async (session, token) =>
{
var pending = await session.Query<PendingJob>().ToListAsync(token);
foreach (PendingJob job in pending)
{
job.MarkStarted();
}
await session.SaveChangesAsync(token);
});The scope remains alive until the async delegate completes.
Every extension has two delegate shapes:
builder.Services.AddHostedService<IWorker>(worker => worker.RunAsync());
builder.Services.AddHostedService<IWorker>((worker, token) => worker.RunAsync(token));Use the token-aware overload for I/O, database work, queues, or anything that should stop promptly during shutdown or cancelled startup.
Each call registers a separate hosted service. They are started by the host in registration order.
builder.Services.AddHostedService<IClockSetup>((setup, token) => setup.InitializeAsync(token));
builder.Services.AddScopedHostedService<IDocumentSession>((session, token) => session.SaveChangesAsync(token));
builder.Services.AddBackgroundService<IQueueWorker>((worker, token) => worker.RunAsync(token));Fluent.Hosting is free and open source software licensed under the MIT License. You can use it in private and commercial projects.
Keep in mind that you must include a copy of the license in your project.