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.
The Problem
Section titled “The Problem”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 wiringbuilder.Services.AddScoped<IOrderService, OrderService>();builder.Services.AddScoped<IProductService, ProductService>();// ... 50 more, growing with every new classbuilder.Services.AddDbContext<AppDbContext>(o => o.UseSqlServer(cs));app.UseAuthentication(); app.UseAuthorization(); // forget one and it breaksThe Solution
Section titled “The Solution”Declare what your application is; the generator handles how it starts up.
// Program.cs — one call wires everythingawait 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.
Packages
Section titled “Packages”| Package | Role |
|---|---|
Pragmatic.Composition | Meta-package (references Abstractions + Host) |
Pragmatic.Composition.Host | ASP.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.
The 3-tier configuration model
Section titled “The 3-tier configuration model”| Tier | Where | What it decides |
|---|---|---|
| Topology (compile-time) | [Module], [Boundary], [BelongsTo<T>], [UsePackage<T>] | Structure & module dependencies — the generator detects it |
| Module strategy | Program.cs via IPragmaticBuilder.Use*() | Infrastructure choices: auth handler, storage, transport |
| Business wiring | IStartupStep | Services, 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.
Installation
Section titled “Installation”dotnet add package Pragmatic.Composition.Hostdotnet add package Pragmatic.SourceGenerator # the unified analyzer(Building inside this monorepo? See Monorepo Structure.)
What the generator gives you
Section titled “What the generator gives you”[Service]/[Decorator]— self-registering services and ordered decorators, noAddScopedlists.[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.
Status
Section titled “Status”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 |
Requirements
Section titled “Requirements”- .NET 10.0+
- ASP.NET Core 10.0+
Pragmatic.SourceGeneratoranalyzer
License
Section titled “License”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).