Skip to content
CAI
Software that uses CAICheck a score

charlessolar/Aggregates.NET

46.0

Weak · 21 September 2026

6.5k

lines of production code

C#

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

Aggregates.NET is a .NET library for building event-sourced applications using the CQRS and DDD patterns. It provides core domain modeling primitives, state management, and integration with NServiceBus and EventStore. The framework includes testing utilities and sample applications to demonstrate its capabilities.

How it got here

2014–2015 — Aggregates.NET framework modernization

9 changes.

This period focused on modernizing the Aggregates.NET library by migrating to Microsoft's standard dependency injection and logging modules, and updating project dependencies to .NET 6.0. The work also introduced comprehensive interfaces and base classes for entity management, state handling, and message processing, establishing a more robust and standardized API for building aggregate roots.

2016–2017 — Core domain modeling and integration extensions

11 changes.

This period focused on establishing the framework's core domain modeling primitives, such as the Id type and state management, while simultaneously building out integrations for EventStore and NServiceBus. The work included adding extension methods for logging, reflection, and messaging, alongside comprehensive unit tests to validate the new infrastructure.

2018–2021 — Testing infrastructure and build migration

10 changes.

This period focused on establishing a robust testing framework, introducing testable abstractions and comprehensive unit tests for the domain and application layers. Concurrently, the project modernized its build system by migrating to Cake.Frosting and adding helper classes for automated build configuration and artifact management.

Features

Add new sample applications demonstrating core Aggregates.NET features

The samples directory now includes four new example projects: a basic 'HelloWorld' sample showing a simple echo service and domain; a 'Snapshots' sample that demonstrates entity snapshotting with a configurable snapshot interval; a 'Children' sample illustrating parent-child entity relationships and unique name constraints; and a 'Queries' sample introducing request/response messaging patterns. Each sample includes full client and domain implementations with NServiceBus integration, structured logging, and console-based interaction loops.

samples · high confidence

Expanded testing infrastructure for domain and application layers

The testing package now includes comprehensive internal support for testing domain and application logic. New exception types (DidNotRaisedException, ExistException, ModelException, NoMatchingEventException, PocoUnequalException, RaisedException, ServiceException) provide detailed error messages for test assertions. The IdRegistry and TestableId classes manage deterministic and generated IDs for test scenarios. TestableDomain, TestableRepository, and TestableEventStore provide in-memory implementations for testing command handlers, event sourcing, and snapshots. TestableApplication and ModelChecker/ModelPlanner allow verification of model state changes. TestableProcessor and TestableEventFactory support service and message testing. These changes enable more robust unit testing of aggregate roots, child entities, and application services.

src/Aggregates.NET.Testing/Internal · high confidence

Introduce CommandSaga for ordered command execution

Added new saga infrastructure (CommandSaga, CommandSagaHandler, and related messages) that enables the ordered, sequential execution of commands within a single saga instance. The handler manages a queue of commands and abort commands, processing them one by one and marking the saga as complete when the queue is exhausted. This provides a mechanism to ensure commands are processed in a specific order and allows for controlled abortion of the sequence.

src/Aggregates.NET.NServiceBus/Sagas · medium confidence

Introduce Entity base class with state management and rule validation

Added the Entity base class in Aggregates.NET, providing a foundation for domain entities with state management, uncommitted event tracking, and a Rule method for business logic validation. The class supports implicit conversion to state, child entity tracking, and snapshotting hooks, enabling entities to manage their own state and validate business rules before applying events.

Aggregates.NET · high confidence

Introduce EventStore client and consumer implementations

Added new internal classes (EventStoreClient, EventStoreConsumer, StoreEvents) that implement the IEventStoreClient, IEventStoreConsumer, and IStoreEvents interfaces to handle EventStore interactions. The EventStoreClient manages connections for streams, projections, and persistent subscriptions, while the consumer and store classes provide the concrete logic for setting up projections, connecting to event streams, and writing/reading events and snapshots.

src/Aggregates.NET.EventStore/Internal · high confidence

Introduce EventStore client configuration and dependency updates

The library now provides a new \ESConfigure\ class that allows users to configure EventStore connections, projection management, and persistent subscriptions via the standard \IServiceCollection\ pattern. This includes registering clients as singletons and setting up startup/shutdown tasks for event subscribers. Additionally, the project has been updated to use EventStore client packages version 23.1.0 and Microsoft.Extensions packages version 8.0.0.

src/Aggregates.NET.EventStore · high confidence

Introduce JSON serialization configuration for ASP.NET Core

The \Aggregates.NET.NewtonsoftJson\ library now provides a \JsonConfigure\ class that registers the \IMessageSerializer\ implementation using \Microsoft.Extensions.DependencyInjection\. This change updates the project's dependencies to use \Microsoft.Extensions.DependencyInjection.Abstractions\ version 8.0.0 and \Newtonsoft.Json\ version 13.0.3, enabling the framework to resolve the JSON message serializer via the standard DI container.

src/Aggregates.NET.NewtonsoftJson · high confidence

Introduce Newtonsoft.Json serialization implementation for message handling

Added new internal components to the Aggregates.NET.NewtonsoftJson library to handle JSON serialization and deserialization of messages. This includes a JsonMessageSerializer that configures Newtonsoft.Json with specific settings (such as disabling TypeNameHandling for security, using a custom contract resolver to support private setters for state snapshots, and a custom serialization binder for type mapping). A NewtonsoftIdJsonConverter is also added to handle Id type serialization. These changes provide the underlying mechanism for serializing and deserializing messages using the Newtonsoft.Json library.

src/Aggregates.NET.NewtonsoftJson/Internal · high confidence

Introduce domain modeling primitives and configuration infrastructure

The library now provides core domain modeling primitives, including a new \Id\ value type that supports implicit conversion to and from string, long, and Guid, along with a generic \State\<TThis\>\ base class for entity state management. A \BusinessException\ class is added to represent business rule failures, and a \Versioned\ attribute is introduced to support entity versioning. The framework's configuration and service registration are formalized through new \Configuration\, \ISettings\, and \IServiceContext\ interfaces, alongside a \ServiceCollectionExtensions\ helper to simplify integration with the Microsoft.Extensions.Hosting pipeline. Additionally, a \Compression\ enum and \Defaults\ constants are introduced to manage event and snapshot compression and header prefixes.

src/Aggregates.NET · high confidence

Introduce testable domain, application, and processor abstractions for easier unit testing

The testing package now exposes a structured API for verifying behavior in unit tests. Developers can use \ITestableDomain\ and \ITestableApplication\ to check or plan events and models, and \ITestableProcessor\ to verify service calls. The \TestableContext\ class provides a concrete implementation that integrates with NServiceBus's testing infrastructure, allowing tests to inspect sent, forwarded, and replied messages, as well as saga state. This simplifies writing unit tests for command handlers, sagas, and processors by providing clear assertions about raised events and model states.

src/Aggregates.NET.Testing · high confidence

Introduces Cake build helper classes for credentials, packages, parameters, paths, and versioning

Added new helper classes in the Cake build system to manage build configuration and artifacts. BuildCredentials retrieves GitHub and Artifactory credentials from environment variables. BuildPackages categorizes projects into NuGet packages, Docker images, binaries, and unit tests. BuildParameters centralizes build settings, including CI environment detection (Azure Pipelines, AppVeyor, GitHub Actions), branch info, and flags for publishing or building specific artifacts. BuildPaths resolves project types (Docker, Web, Test, Library) and defines output directories. BuildVersion calculates semantic versions using GitVersion, with pre-release tags for non-master branches. These changes support a more structured and automated build process.

cake/Helpers · high confidence

Introduces internal infrastructure for child entity tracking and state mutation

The library adds internal classes to support hierarchical entity models and state management. A new \ChildrenProjection\ message and \TrackChildren\ service enable the system to track and retrieve child entities associated with a parent aggregate. The \EntityFactory\ and \Repository\ implementations are updated to handle parent-child relationships, automatically injecting parent references and state into child entities. Additionally, a generic \Enumeration\ base class is introduced to simplify the creation of strongly-typed value objects, and \StateMutators\ are implemented to handle event-to-state application. These changes allow developers to define and manage nested entity structures within their aggregates more easily.

src/Aggregates.NET/Internal · high confidence

New contracts for the .NET Aggregates framework

The Aggregates.NET/Contracts package now exposes a comprehensive set of interfaces that define the core abstractions for the framework. This includes contracts for entity management (IEntity, IChildEntity), state handling (IState, IMutateState), and repository access (IRepository, IRepositoryFactory). The update also introduces interfaces for message handling (IMessageDispatcher, IMessaging), event storage and projection (IStoreEvents, IStoreSnapshots, IEventStoreConsumer), and infrastructure concerns like metrics (IMetrics), time/ randomness providers, and versioning. These changes establish the foundational API for building and testing aggregate roots and their associated behaviors.

src/Aggregates.NET/Contracts · high confidence

New domain-specific exception types for the Aggregates.NET library

The library now includes a set of new, specific exception classes to improve error handling and debugging. These include EndpointVersionException for version conflicts, EntityAlreadyExistsException for duplicate entities, NotFoundException for missing streams, PersistenceException for storage errors, RejectedException for invalid commands, SerializationException for data conversion failures, UnknownMessageException for unrecognized message types, and VersionException for general versioning issues. This allows developers to catch and handle specific failure modes more precisely.

src/Aggregates.NET/Exceptions · high confidence

New extension methods for fire-and-forget and timed-out command sending

The NServiceBus integration now provides new extension methods on \IMessageSession\ and \IMessageHandlerContext\ to send commands without waiting for a response. \PassiveCommand\ allows for fire-and-forget command dispatch, while \TimeoutCommand\ enables sending a command with a specific timeout, returning a boolean indicating if the command completed within the allotted time. These utilities simplify common messaging patterns in the Aggregates.NET library.

src/Aggregates.NET.NServiceBus · high confidence

New extension methods for logging, reflection, and data handling

The library introduces a suite of extension methods in the Aggregates.Extensions namespace to improve logging, reflection, and data handling. LoggerExtensions adds structured logging helpers (LogEvent, DebugEvent, etc.) that support event IDs and exception details. ReflectionExtensions provides factory methods to compile reflection-based handlers into fast delegates for state mutators, query handlers, and repositories. Additional extensions include TaskExtensions for parallel async operations, StringExtensions for hashing and formatting, and StoreExtensions for serialization and compression. These changes enhance performance and observability for developers using the framework.

src/Aggregates.NET/Extensions · high confidence

New message and event interfaces for the Aggregates library

The Aggregates.NET/Messages area now includes new core message interfaces (IMessage, ICommand, IEvent) and specific message types (Accept, Reject, Error) along with endpoint lifecycle events (EndpointAlive, EndpointDead). These additions allow applications to send commands and handle errors or rejections more explicitly, while providing structured events for endpoint status changes.

src/Aggregates.NET/Messages · high confidence

Behavioural changes

Added AssemblyInfo.cs for Aggregates.NET

A new AssemblyInfo.cs file was added to the Aggregates.NET project, establishing standard assembly metadata such as the title, configuration, and a unique GUID. This change supports the broader effort to implement a state and entity design within a .NET Framework project format, ensuring proper assembly identification and COM visibility settings.

src/Aggregates.NET/Properties · high confidence

Migrate build system to Cake.Frosting

The build system has been migrated from the previous implementation to Cake.Frosting, introducing a new solution file (Build.sln) and a structured task-based build script (Program.cs). This change introduces new build tasks including Clean, Generate-NuGet-Config, Restore-NuGet-Packages, Build, and Run-Unit-Tests, along with context extensions for logging and global usings for Cake libraries.

cake · high confidence

Migrated to Microsoft's standard DI and logging modules

The library has been refactored to use Microsoft's standard dependency injection and logging modules, removing direct support for StructureMap, SimpleInjector, and LibLog. This change simplifies the framework's dependencies and aligns with modern .NET practices, though users upgrading from previous versions should be aware that they may need to use Microsoft's libraries or their own adaptors for other DI/logging frameworks.

(repo-wide) · high confidence

NServiceBus integration refactored with new pipeline behaviors

The internal NServiceBus integration has been restructured into a series of new pipeline behaviors to handle message processing, mutation, and error handling. Key additions include CommandAcceptor for handling command replies and business exceptions, FailureReply for notifying clients of service faults, and MessageDetyper for mapping message types. The system now explicitly manages scoped service providers, logs execution timing, and handles saga state transitions, providing a more modular and observable messaging pipeline.

src/Aggregates.NET.NServiceBus/Internal · high confidence

Standardized build configuration and versioning

The project now uses a centralized Common.props file to define shared MSBuild properties, including enabling Source Link for improved debugging, embedding PDBs, and setting standard NuGet metadata (author, license, repository URL). Additionally, a new SharedAssemblyInfo.cs file has been introduced to manage assembly-level metadata and versioning (currently set to 0.17.0.0) across the solution.

src · high confidence

Test coverage

Added test infrastructure and test doubles; Added unit tests for EventStore consumer and event storage; Added unit tests for NServiceBus integration components; Added unit tests for common extension methods; Added unit tests for common infrastructure components; Added unit tests for exception handling; Added unit tests for the testing framework's testable context, model, and service checkers.

Dependencies

Update project dependencies and build configuration

The build system and sample projects have been updated to target .NET 6.0 and use modern .NET SDK-style project files. Dependencies for NServiceBus, EventStore, and Microsoft.Extensions libraries have been upgraded to their latest compatible versions (e.g., NServiceBus 8.1.6, Microsoft.Extensions 8.0.0), and the Cake build script has been migrated to use Cake.Frosting with updated tooling packages.

(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 51 → 46 (-4.7)
  • Rubric changed (rubric-2026.08.18 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 50 → 36 (-14.5)
  • Architecture 74 → 73 (-1.3)
  • Maturity 45 → 45 (+0.0)
  • Readiness 56 → 56 (-0.3)
  • Security 67 → 76 (+9.6)
  • Domain Modelling 99 (new)
  • Performance 62 → 62 (+0.0)

Resolved (29)

  • Bounded contexts not declared
  • Change coupling: MutateIncoming.cs ↔ MutateOutgoing.cs (src/Aggregates.NET.NServiceBus/Internal/MutateIncoming.cs)
  • Duplicate method name 'Plan' with different parameter types (TestableId vs Id) causing ambiguity.
  • Duplicated block (13 lines × 2) (src/Aggregates.NET.EventStore/Internal/EventStoreClient.cs)
  • Duplicated block (6 lines × 2) (src/Aggregates.NET.NServiceBus/Internal/NSBMutator.cs)
  • Duplicated block (9 lines × 2) (src/Aggregates.NET/Internal/UnitOfWork.cs)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • Inconsistent naming for repository retrieval operations. Some use 'Get' while others use 'Plan' for similar retrieval/lookup operations on entities.
  • Inconsistent naming for retrieval operations. 'Get' implies a mandatory return (or exception on failure), while 'TryGet' implies a safe, non-throwing retrieval. However, both 'Get' and 'TryGet' in the interface return the entity (not a bool/optional), making the semantic difference between 'Get' and 'TryGet' confusing. Additionally, 'Get' and 'TryGet' have identical signatures (plus bucket), suggesting they might be redundant or one should return an optional/nullable type instead of throwing.
  • Inconsistent naming for verification/checking operations. Some use 'Check' while others use 'Raised' or 'EventChecker' for similar verification logic.
  • Inconsistent setup methods for event consumption. 'IEventSubscriber' uses 'Setup' for general endpoints, while 'IEventStoreConsumer' uses 'SetupProjection' and 'SetupChildrenProjection'. This splits the concept of 'starting to listen' into multiple methods with different signatures and naming conventions.
  • Monorepo: only 1 of 7 solutions was scored
  • No ADRs found
  • Overloaded method 'Plan' exists with different parameter types, which can be confusing.
  • …and 9 more

New (147)

  • Ambiguous distinction between Get and TryGet. In many ORMs/Repositories, Get throws on failure while TryGet returns null/optional. However, without seeing return types (Task<TEntity> vs Task<TEntity?>), it is unclear if TryGet is truly safer or just a naming variant. If both return the same type, the distinction is purely exception-based, which is often considered an anti-pattern in modern C# APIs (prefer TryGet returning bool/optional).
  • CRAP 182: UnitOfWorkExecutor.Invoke (src/Aggregates.NET.NServiceBus/Internal/UnitOfWorkExecutor.cs)
  • CRAP 30: CommandSagaHandler.SendNextCommand (src/Aggregates.NET.NServiceBus/Sagas/CommandSagaHandler.cs)
  • CRAP 30: CommandSagaHandler.checkCompleted (src/Aggregates.NET.NServiceBus/Sagas/CommandSagaHandler.cs)
  • CommentedOutCode (src/Aggregates.NET.UnitTests/Common/Entity.cs)
  • CommentedOutCode (src/Aggregates.NET.UnitTests/Common/Entity.cs)
  • CommentedOutCode (src/Aggregates.NET.UnitTests/Common/Entity.cs)
  • CommentedOutCode (src/Aggregates.NET.UnitTests/Common/Entity.cs)
  • CommentedOutCode (src/Aggregates.NET.UnitTests/Common/Entity.cs)
  • CommentedOutCode (src/Aggregates.NET.UnitTests/NServiceBus/MessageIdentifier.cs)
  • CommentedOutCode (src/Aggregates.NET.UnitTests/NServiceBus/UnitOfWorkExecutor.cs)
  • CommentedOutCode (src/Aggregates.NET.UnitTests/NServiceBus/UnitOfWorkExecutor.cs)
  • CommentedOutCode (src/Aggregates.NET.UnitTests/NServiceBus/UnitOfWorkExecutor.cs)
  • CommentedOutCode (src/Aggregates.NET.UnitTests/NServiceBus/UnitOfWorkExecutor.cs)
  • CoverageExclusion (src/Aggregates.NET.EventStore/ESConfigure.cs)
  • CoverageExclusion (src/Aggregates.NET.EventStore/ESConfigure.cs)
  • CoverageExclusion (src/Aggregates.NET.EventStore/Internal/EventStoreClient.cs)
  • CoverageExclusion (src/Aggregates.NET.EventStore/Internal/EventStoreConsumer.cs)
  • CoverageExclusion (src/Aggregates.NET.NServiceBus/BusExtensions.cs)
  • CoverageExclusion (src/Aggregates.NET.NServiceBus/ContextExtensions.cs)
  • …and 127 more

Architecture

  • Unchanged — 1 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

charlessolar/Aggregates.NET 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 3e8efc9ae55d3392cecc43cc657829b41e908f9a — 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.