Skip to content

Pragmatic.Composition

Source-generated application composition and dependency injection for .NET 10. Declare modules, services, and startup steps; the generator writes all the wiring — zero reflection, no runtime assembly scanning.

Every .NET app accumulates the same startup ceremony: register services one by one, order middleware, wire DbContexts, keep it consistent across modules. With 50+ services, Program.cs becomes a wall of services.AddScoped<>() that no one wants to maintain — and forgetting one line silently breaks the app.

// Without Pragmatic: 80+ lines of mechanical wiring
builder.Services.AddScoped<IOrderService, OrderService>();
builder.Services.AddScoped<IProductService, ProductService>();
// ... 50 more, growing with every new class
builder.Services.AddDbContext<AppDbContext>(o => o.UseSqlServer(cs));
app.UseAuthentication(); app.UseAuthorization(); // forget one and it breaks

Declare what your application is; the generator handles how it starts up.

// Program.cs — one call wires everything
await PragmaticApp.RunAsync(args, app =>
{
if (app.Environment.IsDevelopment()) app.UseDatabaseEnsureCreated();
app.UseAuthentication<NoOpAuthenticationHandler>("PragmaticDefault");
});
// Module topology — one class per bounded context
[Module]
[Include<OrdersModule, AppDatabase>]
[Include<BillingModule, FinancialDatabase>]
public sealed class MyAppModule;
// Services register themselves
[Service]
public class OrderService(IOrderRepository repository) : IOrderService { }

The generator emits the complete host startup — infrastructure auto-registration, ordered startup steps, database init, endpoint mapping, telemetry, maintenance mode — at compile time. Cross-assembly discovery works through [PragmaticMetadata] assembly attributes: libraries declare what they register, the host aggregates automatically.

PackageRole
Pragmatic.CompositionMeta-package (references Abstractions + Host)
Pragmatic.Composition.HostASP.NET Core runtime: PragmaticApp, IStartupStep, scanning, telemetry, remote boundaries, maintenance mode

Attributes ([Service], [Module], [StartupStep], …) live in Pragmatic.Abstractions, so domain modules use them without referencing ASP.NET Core.

TierWhereWhat it decides
Topology (compile-time)[Module], [Boundary], [BelongsTo<T>], [UsePackage<T>]Structure & module dependencies — the generator detects it
Module strategyProgram.cs via IPragmaticBuilder.Use*()Infrastructure choices: auth handler, storage, transport
Business wiringIStartupStepServices, filters, OpenAPI, feature-specific DI + HTTP pipeline

Defaults always work: a bare await PragmaticApp.RunAsync(args) boots with safe in-memory / passthrough / allow-all defaults; you override only what you need. See Startup Pipeline.

Terminal window
dotnet add package Pragmatic.Composition.Host
dotnet add package Pragmatic.SourceGenerator # the unified analyzer

(Building inside this monorepo? See Monorepo Structure.)

  • [Service] / [Decorator] — self-registering services and ordered decorators, no AddScoped lists.
  • [Module] / [Include<…>] — module topology and per-module databases.
  • [StartupStep] / IStartupStep — ordered business wiring + HTTP pipeline configuration.
  • IPragmaticBuilder.Use*() — module strategy (auth, storage, messaging, …).
  • Remote boundaries[RemoteBoundary<T>] generates typed HTTP invokers for cross-service calls.
  • Maintenance mode, telemetry, and database initialization, wired automatically.

The composition model, service/decorator registration, startup steps, builder, remote boundaries, and maintenance mode are functional within the 0.8 preview. See the roadmap.

| Concepts | Composition model, metadata aggregation, the 3-tier configuration model | | Getting Started | Your first module, service, and PragmaticApp.RunAsync | | Service Registration | [Service], lifetimes, [Decorator], keyed services | | Startup Pipeline | IStartupStep, IPragmaticBuilder, ordering, HTTP pipeline | | Remote Boundaries | [RemoteBoundary<T>], typed HTTP invokers, the invoke endpoint | | Common Mistakes | The most frequent composition pitfalls | | Troubleshooting | Problem/solution guide with diagnostics |

  • .NET 10.0+
  • ASP.NET Core 10.0+
  • Pragmatic.SourceGenerator analyzer

Part of the Pragmatic.Design ecosystem — see Licensing. Pragmatic.Composition is licensed under the PolyForm Small Business 1.0.0 license (free for small businesses; commercial license above the threshold).