Skip to content

Structural Dependencies

ChronicleOptions is designed to hold runtime configuration that can be bound from appsettings.json or environment variables — connection strings, timeouts, TLS settings, naming policies, and so on.

Services and providers that must be resolved at registration time (before the DI container is built) are called structural dependencies. These are not configuration values and cannot be meaningfully bound from appsettings.json. They are passed directly as constructor arguments to ChronicleClient or set on IChronicleBuilder when using the DI-hosted setup (IHostApplicationBuilder, WebApplicationBuilder).

DependencyPurposeDefault
IClientArtifactsProviderDiscovers event types, projections, reactors, reducers, and other artifacts at startupDefaultClientArtifactsProvider (auto-discovers from loaded assemblies)
IIdentityProviderSupplies the current user’s identity for event metadataBaseIdentityProvider (empty identity)
ICorrelationIdAccessorProvides the current correlation ID for event metadataCorrelationIdAccessor (generates a new ID per call)
IEventStoreNamespaceResolverResolves the event store namespace for each operationDefaultEventStoreNamespaceResolver (always returns the default namespace)
ILoggerFactoryCreates loggers for the Chronicle client internalsLoggerFactory (no-op)

For console applications or other non-DI scenarios, pass structural dependencies as named constructor parameters:

var client = new ChronicleClient(
options,
artifactsProvider: myProvider,
loggerFactory: LoggerFactory.Create(b => b.AddConsole()));

All parameters are optional. Any parameter you omit uses the default shown in the table above.

In DI-hosted applications (ASP.NET Core, worker services, or any IHostApplicationBuilder-based host), use the configure callback on AddCratisChronicle to set structural dependencies via the IChronicleBuilder fluent API. This callback runs at registration time, before the DI container is built.

builder.AddCratisChronicle(
configureOptions: options => // runtime config — bindable from appsettings.json
{
options.EventStore = "my-store";
options.ConnectionString = "chronicle://server:35000";
},
configure: b => b // structural dependencies
.WithArtifactsProvider(myCustomProvider)
.WithIdentityProvider(myIdentityProvider));

The same pattern works with WebApplicationBuilder in ASP.NET Core:

// ASP.NET Core — WebApplicationBuilder
var builder = WebApplication.CreateBuilder(args);
builder.AddCratisChronicle(
configureOptions: options => options.EventStore = "my-store",
configure: b => b
.WithIdentityProvider(myIdentityProvider));

The two callbacks are intentionally separate:

  • configureOptions feeds the options pipeline and can be overridden by appsettings.json or IConfiguration.
  • configure sets structural dependencies at registration time and is not overridable by configuration.
MethodSets
WithArtifactsProvider(IClientArtifactsProvider)Custom artifact discovery
WithIdentityProvider(IIdentityProvider)Custom identity resolution
WithCorrelationIdAccessor(ICorrelationIdAccessor)Custom correlation ID accessor
WithNamespaceResolver(IEventStoreNamespaceResolver)Custom namespace resolution

Implement IClientArtifactsProvider when you need to control exactly which types Chronicle discovers. This is useful in modular applications or when using assembly scanning that differs from the default:

public class MyArtifactsProvider : IClientArtifactsProvider
{
public IEnumerable<Type> EventTypes => [typeof(BookBorrowed), typeof(BookReturned)];
public IEnumerable<Type> Projections => [typeof(BorrowedBooksProjection)];
public IEnumerable<Type> Reactors => [];
// ... other members
}
builder.AddCratisChronicle(
configureOptions: options => options.EventStore = "my-store",
configure: b => b.WithArtifactsProvider(new MyArtifactsProvider()));

DefaultClientArtifactsProvider scans loaded assemblies for artifacts at first access (lazy initialization). You can construct it with a custom assembly provider:

var assembliesProvider = new CompositeAssemblyProvider(
ProjectReferencedAssemblies.Instance,
PackageReferencedAssemblies.Instance);
var artifactsProvider = new DefaultClientArtifactsProvider(assembliesProvider);

The static DefaultClientArtifactsProvider.Default instance is used when no provider is supplied.

Note: DefaultClientArtifactsProvider initializes lazily on first property access; no explicit initialization is required.