huysentruitw/Aggregator
50.5
Adequate · 21 September 2026
1.3k
lines of production code
C#
with TypeScript
4
measurements over time
What this system is
This system is an event-sourcing framework for .NET that manages aggregate roots and their state changes. It provides a command processing pipeline that dispatches domain events and persists them to an event store. The library supports multiple dependency injection containers and includes a fluent testing API for verifying aggregate behavior.
How it got here
2018 — Architecture modernization and DI integration
21 changes.
The project underwent a significant architectural refactoring to simplify the core AggregateRoot implementation and introduce asynchronous, dependency-injection-friendly patterns. This period saw the migration of the test suite to xUnit, the introduction of a custom event dispatcher, and the addition of Microsoft.Extensions.DependencyInjection support alongside a new EventStore persistence layer.
2019–2020 — Testing infrastructure and sample expansion
4 changes.
This period focused on enhancing the framework's testability by introducing a fluent testing library for aggregate roots and expanding the Kanban sample with comprehensive domain and integration tests. Additionally, the KanbanStyle sample was augmented with a full ASP.NET Core and Angular 6 frontend template.
Features
Add ASP.NET Core Angular application template
The KanbanStyle sample now includes a complete ASP.NET Core application template featuring an Angular 6.0.0 client-side application. This adds a new frontend structure with components for navigation, home, counter, and data fetching, alongside a backend WeatherForecast API endpoint. The project also includes standard configuration files for the Angular CLI, TypeScript, and build processes.
samples/KanbanStyle · high confidence
Add Aggregator DI extension methods for service registration
A new extension class, ServiceCollectionExtensions, has been added to the Microsoft.Extensions.DependencyInjection namespace. This provides two new methods, AddAggregator, which allow users to register the Aggregator library's core dependencies—including ICommandProcessor, IRepository, IEventDispatcher, and related context classes—directly on the IServiceCollection. This simplifies the setup process by bundling the necessary service registrations into a single, chainable call.
src/Aggregator.Microsoft.DependencyInjection/Extensions · high confidence
Add Aggregator.Testing library for fluent aggregate testing
The Aggregator.Testing library has been added, providing a fluent API for testing aggregate roots. This includes a new AggregatorTestingException, and fluent continuation classes (Scenario, GivenContinuation, WhenContinuation, ThenContinuation, ThrowsContinuation) that allow users to write tests by chaining method calls to verify expected events or exceptions.
src/Aggregator.Testing · high confidence
Add EventStore persistence implementation
Introduces a new EventStore-based persistence layer for the Aggregator framework. The \EventStore\ class provides methods to check if an aggregate root exists (\Contains\) and retrieve its event stream (\GetEvents\). The \EventStoreTransaction\ class handles buffering and committing or rolling back batches of events, supporting optimistic concurrency control via version checking. This adds a concrete, production-ready implementation for event sourcing using the EventStore database.
src/Aggregator.Persistence.EventStore · high confidence
Add Microsoft.Extensions.DependencyInjection integration
The Aggregator library now supports Microsoft's dependency injection container. This change introduces \ServiceScope\ and \ServiceScopeFactory\ implementations that wrap the standard \IServiceScope\ and \IServiceProvider\ interfaces, allowing users to resolve services and manage scopes within the Aggregator framework using the Microsoft.Extensions.DependencyInjection API.
src/Aggregator.Microsoft.DependencyInjection · high confidence
Introduce custom event dispatcher for command processing
Added a new \EventDispatcher\ class and its \IEventDispatcher\ interface to handle event dispatching within the \CommandProcessor\. This implementation uses reflection to invoke generic handler methods for each event, allowing the system to process multiple events generated by a single command execution.
src/Aggregator/Event · high confidence
Repository structure and configuration files added
The repository was initialized with core documentation and configuration files, including CONTRIBUTING.md, LICENSE.txt, and README.md. Additionally, build and CI configurations (appveyor.yml, .editorconfig, .gitignore) and solution structure (Aggregator.sln) were added to support the project's development workflow.
(repo-wide) · high confidence
Behavioural changes
Async persistence interfaces and repository implementation
The Aggregator.Persistence layer introduces a new IRepository interface and concrete Repository class for managing aggregate roots, including methods to check existence, retrieve, and add aggregates. The IEventStore interface is updated to support asynchronous operations, adding a Contains method and a GetEvents method that accepts a minimum version. Additionally, the IEventStoreTransaction interface is modified to make Commit, Rollback, and StoreEvents methods asynchronous (returning Task) and renames the expected revision parameter to expectedVersion with a long type.
src/Aggregator/Persistence · medium confidence
Refactor internal aggregate root tracking to use a new AggregateRootEntity wrapper
The internal unit of work now tracks aggregate roots using a new AggregateRootEntity class, which encapsulates the identifier, the aggregate root, and the expected version. This replaces the previous approach of storing the raw IAggregateRootChangeTracker in the unit of work's dictionary. Additionally, the IAggregateRootChangeTracker interface has been simplified by removing the Identifier and ExpectedRevision properties (now handled by the wrapper) and changing the GetChanges method to return a TEventBase\[\] array instead of an IEnumerable.
src/Aggregator/Internal · high confidence
Refactored Autofac integration and command handling scope
The Autofac module has been refactored to simplify dependency injection and remove the previous command-handling scope mechanism. The old \CommandHandlingScope\ and \CommandHandlingScopeFactory\ classes have been removed in favor of a simpler \ServiceScope\ and \ServiceScopeFactory\ implementation. Additionally, the \ICommandHandler\ interface was moved to the \Aggregator.Abstractions\ project and updated to include a \CancellationToken\ in its \Handle\ method, allowing commands to be cancelled. The \AggregatorModule\ now registers the \CommandProcessor\ and \Repository\ types directly, streamlining the container setup.
src/Aggregator.Autofac · medium confidence
Refactored command processing to use dependency injection and event dispatching
The command processor now resolves command handlers via a service scope rather than a custom scope factory, and explicitly dispatches events through an IEventDispatcher. This change introduces transactional event storage with automatic rollback on failure, adds configurable notification handlers for pre-processing and event enrichment, and supports cancellation via CancellationToken.
src/Aggregator/Command · medium confidence
Refine exception hierarchy and add new domain-specific exceptions
The exception handling in the Aggregator module has been refactored to simplify the base class and introduce new, specific exceptions. The base \AggregateRootException\ and its generic variant \AggregateRootException\<TIdentifier\>\ have been simplified by removing the \innerException\ constructor overloads, meaning inner exceptions are no longer supported for these types. Additionally, three new exception types have been introduced: \AggregateRootAlreadyAttachedException\ (thrown when an aggregate root is attached twice), \AggregateRootAlreadyExistsException\ (thrown when adding a duplicate aggregate root), and \AggregateRootNotFoundException\ (thrown when an aggregate root is not found). Furthermore, \HandlerForEventAlreadyRegisteredException\ and \UnhandledEventException\ have been decoupled from the generic \AggregateRootException\<TIdentifier\>\ base class, removing the generic type parameter and the associated identifier property, simplifying their signatures to focus on the event type.
src/Aggregator/Exceptions · high confidence
Simplified AggregateRoot base class and changed change tracking to a queue
The generic AggregateRoot class no longer requires a separate identifier type parameter, as the identifier and expected version have been removed from this base class. Internally, the collection of pending changes has been switched from a List to a Queue, and the GetChanges method now returns an array instead of an IEnumerable. These changes streamline the aggregate root implementation by removing redundant state and enforcing a first-in-first-out order for change tracking.
Aggregator · medium confidence
Updated assembly visibility configuration for test projects
The internal visibility attributes in the Aggregator assembly have been updated to include strong-name public key tokens for the test projects. This change ensures that the test assemblies can access internal members of the Aggregator library, which is necessary for unit testing internal implementation details.
src/Aggregator · high confidence
Test coverage
Added domain model and command handler tests for the Kanban sample; Added unit tests for EventDispatcher; Added unit tests for EventStore and EventStoreTransaction; Added unit tests for Microsoft DI integration; Added unit tests for command handling, processing, and dependency injection; Added unit tests for the Aggregator testing framework; Added unit tests for the persistence layer's Repository class; Migrate Aggregator.Tests to xUnit and add coverage for AggregateRootEntity; Migrate Aggregator.Tests to xUnit and expand test coverage; Migrated Autofac test suite to xUnit.
Dependencies
Update .NET target frameworks and test dependencies
The project files for the Aggregator library and its samples have been updated to target .NET Standard 2.0 and 2.1, replacing the previous .NET Core 2.0/4.7.1 targets. Additionally, the test projects have been migrated from NUnit to xUnit, and dependencies such as Autofac and Moq have been updated to their latest compatible versions.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.
Score
- CAI 55 → 51 (-4.1)
- Rubric changed (rubric-2026.08.18 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 84 → 78 (-5.2)
- Architecture 91 → 91 (-0.3)
- Maturity 47 → 47 (+0.0)
- Readiness 45 → 41 (-3.6)
- Security 99 → 64 (-35.5)
- Performance 66 → 66 (+0.0)
Resolved (10)
- Bounded contexts not declared
- Coverage not measured — analyzer environment
- Low XML-doc coverage: Aggregator.Testing(netstandard2.0) (src/Aggregator.Testing/Aggregator.Testing.csproj)
- Low: security finding (details withheld)
- Low: security finding (details withheld)
- Monorepo: only 1 of 2 solutions was scored
- No exposed public API
- Test runner surfaced no tests
- dormant codebase — no living knowledge left to concentrate
- redundant comment (tests/Aggregator.Autofac.Tests/ServiceScopeFactoryTests.cs)
New (28)
- CoverageExclusion (src/Aggregator.Autofac/AggregatorModule.cs)
- CoverageExclusion (src/Aggregator.Autofac/AggregatorModule.cs)
- CoverageExclusion (src/Aggregator.Microsoft.DependencyInjection/Extensions/ServiceCollectionExtensions.cs)
- CoverageExclusion (src/Aggregator.Persistence.EventStore/EventStore.cs)
- CoverageExclusion (src/Aggregator.Persistence.EventStore/EventStore.cs)
- CoverageExclusion (src/Aggregator.Persistence.EventStore/EventStore.cs)
- CoverageExclusion (src/Aggregator.Persistence.EventStore/EventStoreTransaction.cs)
- Documentation: no usage examples (README.md)
- End-of-life runtime: .NET netcoreapp3.1
- High secret: WD-SECRET-0001 (src/Aggregator.Abstractions/keyfile.snk)
- High secret: WD-SECRET-0001 (src/Aggregator.Autofac/keyfile.snk)
- High secret: WD-SECRET-0001 (src/Aggregator.Microsoft.DependencyInjection/keyfile.snk)
- High secret: WD-SECRET-0001 (src/Aggregator.Persistence.EventStore/keyfile.snk)
- High secret: WD-SECRET-0001 (src/Aggregator/keyfile.snk)
- Leaked secret: private-key-blob (src/Aggregator.Abstractions/keyfile.snk)
- Leaked secret: private-key-blob (src/Aggregator.Autofac/keyfile.snk)
- Leaked secret: private-key-blob (src/Aggregator.Microsoft.DependencyInjection/keyfile.snk)
- Leaked secret: private-key-blob (src/Aggregator.Persistence.EventStore/keyfile.snk)
- Leaked secret: private-key-blob (src/Aggregator/keyfile.snk)
- Low: security finding (details withheld)
- …and 8 more
API surface
- Unchanged — 1 HTTP endpoints
Architecture
- Unchanged — 0 containers · 1 contexts · 0 edges
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
huysentruitw/Aggregator was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 21 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit d78423b561164d4ba568a1dd2931e8599fd09fd6 — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-28e75b8e3254.