Skip to content

v2.0.0

Choose a tag to compare

@cbcrouse cbcrouse released this 09 Feb 22:10

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 IServiceCollection or IConfiguration
  • 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 IServiceCollection extension 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 ServiceRegistrationPipeline and ServiceCompositionRoot
  • 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.