v2.0.0
ServiceComposition.NET v2.0.0 🎉
This release introduces ServiceComposition.NET, the evolution of the original StartupOrchestration.NET library.
While the underlying goal remains the same—clean, predictable service registration—this version represents a deliberate architectural shift toward explicit, hosting-agnostic service composition.
Why this change?
Over time, it became clear that the original name and abstractions no longer reflected what the library actually enforces.
The core problem this library solves is not startup configuration—it’s service composition.
Specifically:
- Defining what services are registered
- Enforcing when they are registered
- Keeping registration logic independent of hosting models and presentation layers
To reflect that clarity, the library has been renamed to ServiceComposition.NET, and the API has been simplified around two core concepts:
- Service registration pipelines
- Explicit composition roots
What’s new in v2.0.0?
🧩 Explicit Service Registration Pipelines
Service registrations are now defined as ordered, validated pipelines that:
- Declare what gets registered
- Do not own or create
IServiceCollectionorIConfiguration - Can be executed by any host (web, console, background service, tests)
This guarantees consistent registration order and avoids startup logic being scattered across multiple projects.
🧱 Composition Roots Replace Startup-Oriented Abstractions
Instead of inheriting from Startup-style base classes, presentation layers now:
- Own startup execution
- Explicitly invoke service composition
- Add presentation-specific registrations after core pipelines run
This removes hidden behavior and makes startup flow easy to trace and test.
🔍 Expression-Based Registration with Validation
All service registrations are captured as:
Expression<Action<IServiceCollection, IConfiguration>>This enables:
- Early validation (only valid
IServiceCollectionextension methods are allowed) - Predictable execution order
- Detailed startup logging with human-readable output
Invalid registrations fail fast when added, not at runtime.
🧪 First-Class Testability
Pipelines can be executed directly against a ServiceCollection and Configuration instance:
- No host required
- No
WebApplicationFactory - No test-only startup paths
This makes service composition behavior easy to verify in isolation.
📜 Startup-Time Logging
Each registration emits trace-level logs:
- When it starts
- When it completes
- When it fails
This is especially useful for diagnosing failures that occur before the host is fully running.
Breaking changes
This release intentionally breaks from the original startup-centric model.
Notable changes include:
- Renamed package: StartupOrchestration.NET → ServiceComposition.NET
- Removal of
StartupOrchestrator-style inheritance - Introduction of explicit
ServiceRegistrationPipelineandServiceCompositionRoot - Presentation layers now explicitly execute composition
For these reasons, this release is published as v2.0.0 under a new package name.
The original StartupOrchestration.NET package remains available at v1.1.0 and is not affected.
Migration guide (high level)
Most migrations are straightforward and mechanical.
1️⃣ Replace startup orchestrators with pipelines
Move shared service registrations into a ServiceRegistrationPipeline:
public sealed class CoreServicesPipeline : ServiceRegistrationPipeline
{
protected override ILogger StartupLogger => NullLogger.Instance;
public CoreServicesPipeline()
{
AddRegistration((services, config) =>
services.AddSingleton<IMyService, MyService>());
}
}2️⃣ Introduce a composition root in the presentation layer
Create a composition root that executes the pipeline and adds presentation services:
public sealed class WebServiceCompositionRoot
: ServiceCompositionRoot<CoreServicesPipeline>
{
public WebServiceCompositionRoot()
{
AddRegistration(services =>
services.AddAuthorization());
}
}3️⃣ Execute composition from the host
Your host (web app, console app, etc.) controls execution:
var builder = WebApplication.CreateBuilder(args);
var compositionRoot = new WebServiceCompositionRoot();
compositionRoot.ConfigureServices(builder.Services, builder.Configuration);4️⃣ (Optional) Simplify tests
You can now execute pipelines directly in tests without spinning up a host.
Final notes
ServiceComposition.NET v2.0.0 is a clean baseline, not a patch release.
If you’re starting a new project or untangling startup logic that has become brittle or confusing, this version offers a clear, explicit, and testable way to compose services across hosting models.