Cocoar.Configuration
0.11.1
See the version list below for details.
dotnet add package Cocoar.Configuration --version 0.11.1
NuGet\Install-Package Cocoar.Configuration -Version 0.11.1
<PackageReference Include="Cocoar.Configuration" Version="0.11.1" />
<PackageVersion Include="Cocoar.Configuration" Version="0.11.1" />
<PackageReference Include="Cocoar.Configuration" />
paket add Cocoar.Configuration --version 0.11.1
#r "nuget: Cocoar.Configuration, 0.11.1"
#:package Cocoar.Configuration@0.11.1
#addin nuget:?package=Cocoar.Configuration&version=0.11.1
#tool nuget:?package=Cocoar.Configuration&version=0.11.1
Cocoar.Configuration
Lightweight, strongly-typed, deterministic multi-source configuration layering for .NET (Current target framework: net9.0).
Why Cocoar.Configuration?
Deterministic, strongly-typed, rule-driven configuration layering that complements Microsoft.Extensions.Configuration
.
Design Goals at a Glance
- Explicit ordered layering: Deterministic last-write-wins per key.
- Typed direct injection: Inject config classes or mapped interfaces (no
IOptions<T>
ceremony). - Atomic snapshot recompute: Full ordered rebuild on change → consistent view for all consumers.
- Dynamic rule factories: Later rules can read earlier in-progress snapshots to shape options/queries.
- Pluggable provider model: File, environment, HTTP polling, Microsoft adapter, static & custom.
- DI lifetimes & keys: Configure singleton (default), scoped, transient, keyed variants per type.
- Per-type diagnostics: Inspect merged snapshots when troubleshooting.
- Interoperability: Bring any existing
IConfigurationSource
via the Microsoft Adapter package.
Installation
Supported TFM: net9.0 (multi-targeting planned).
<ItemGroup>
<PackageReference Include="Cocoar.Configuration" />
<PackageReference Include="Cocoar.Configuration.DI" />
<PackageReference Include="Cocoar.Configuration.AspNetCore" />
<PackageReference Include="Cocoar.Configuration.HttpPolling" />
<PackageReference Include="Cocoar.Configuration.MicrosoftAdapter" />
</ItemGroup>
CLI:
dotnet add package Cocoar.Configuration
dotnet add package Cocoar.Configuration.DI
dotnet add package Cocoar.Configuration.AspNetCore
dotnet add package Cocoar.Configuration.HttpPolling
dotnet add package Cocoar.Configuration.MicrosoftAdapter
Quick Start
Minimal example (file + environment layering, strongly-typed access):
// ...
builder
.AddCocoarConfiguration([
Rule.From.File("appsettings.json").Select("App").For<AppSettings>(),
Rule.From.Environment("APP_").For<AppSettings>()
]);
Then inject your config type directly:
var settings = app.Services.GetRequiredService<AppSettings>();
Console.WriteLine($"FeatureX: {settings.EnableFeatureX}");
Simple Setup (Auto-Registration)
Add rules; everything (concrete types + manager) is available immediately.
services.AddCocoarConfiguration([rules]);
➡ Full runnable: Examples/BasicUsage
Interface Binding Setup
Add interface mappings (optional, works with or without DI):
services.AddCocoarConfiguration([rules], [
Bind.Type<DatabaseConfig>().To<IDatabaseConfig>()
]);
➡ Full runnable: Examples/BindingExample
Advanced Setup (Full Control)
Override lifetimes, disable or extend auto-registration, add keyed services:
services.AddCocoarConfiguration([rules], [bindings], opts => {
opts.DefaultRegistrationLifetime(ServiceLifetime.Singleton);
opts.Register.Add<IPaymentConfig>(ServiceLifetime.Scoped, "backup");
});
➡ Full runnable: Examples/ServiceLifetimes
Binding vs DI Registration
These two concerns are independent and intentionally separated:
Concern | What You Define | Purpose | Where |
---|---|---|---|
Binding | Bind.Type<PaymentConfig>().To<IPaymentConfig>() |
Map concrete config types to one or more interfaces for clean consumption | Core (works without DI) |
DI Registration | options.Register.Add<IPaymentConfig>(ServiceLifetime.Scoped, "backup") |
Control lifetimes, add/remove, keyed registrations in the host container | DI Package (Cocoar.Configuration.DI ) |
Key points:
- You can use bindings without DI (access via
ConfigManager
interface lookups). - You can use DI auto-registration without any bindings (inject concrete types directly).
- Combine them for the richest experience: bind interfaces, let DI auto-register both.
- Disable auto-registration with
options.DefaultRegistrationLifetime(null)
and take full manual control viaoptions.Register
.
Minimal patterns:
services.AddCocoarConfiguration([rules]); // Concrete only
services.AddCocoarConfiguration([rules], [bindings]); // + Interfaces
services.AddCocoarConfiguration([rules], [bindings], opts => { /* control */ });
When to Add Bindings?
- Start with concrete types only while exploring providers.
- Add a binding when: multiple consumers need a narrowed contract, or you want to hide writeable/internal members.
- Bind multiple interfaces to the same concrete when different views (read-only, subset) are needed.
- Skip bindings entirely if you only inject config into a composition root or a small number of services.
Concepts
- Rule: Source + optional query + target configuration type
- Binding: Maps concrete configuration types to interfaces for clean DI
- Provider: Pluggable source (file, env, HTTP, static, custom, adapter)
- Merge: Ordered last-write-wins per flattened key
- Recompute: Incremental – only recompute from earliest changed rule; atomic snapshot publish.
- Dynamic dependencies: Rule factories (options/query) can read earlier in-progress rule outputs during a pass.
- Required vs Optional: Optional failure skips the layer.
- DI Auto-Registration: Auto-registers config types and bound interfaces - configurable and can be disabled.
- Service Control: Fine-grained Add/Remove control over service lifetimes and keys
👉 Read more in the Concepts Deep Dive
Providers
Built-in and extension providers:
Provider | Package | Change Signal | Notes |
---|---|---|---|
Static | Core | ❌ | Seed defaults, compose values |
File (JSON) | Core | ✅ Filesystem watcher | Deterministic layering |
Environment | Core | ❌ | Prefix filter; __ & : nesting |
HTTP Polling | Extension | ✅ | Interval polling, payload diffing |
Microsoft Adapter | Extension | Depends | Any IConfigurationSource |
👉 See Providers Overview for full details.
Advanced Features
- Complete DI Integration: Zero-config auto-registration with
Cocoar.Configuration.DI
package - Interface Binding System: Clean separation with
Bind.Type<T>().To<Interface>()
mappings - Service Lifetime Control: Configurable default lifetimes plus fine-grained Remove/Add methods
- Keyed Services: Multiple registrations per type with service keys
- Fail-Safe API: Impossible to forget method calls - always works out of the box
- Generic Provider API:
Rule.From.Provider<>()
for full control - Microsoft Adapter: wrap any
IConfigurationSource
- HTTP Polling Provider: auto-change detection
👉 Details in Advanced Features
Security
- Never commit secrets to JSON files in your repository
- Use environment variable overlays or dedicated secret management systems
- For remote providers: Always use TLS, set reasonable timeouts, and include auth headers when needed
- Consider using Azure Key Vault, AWS Secrets Manager, or similar via the Microsoft Adapter
Examples
Multi-project solution under src/Examples/
with runnable demos:
Core Examples:
- BasicUsage – File + environment layering with interface binding
- SimplifiedCoreExample – Pure core library usage (no DI)
- BindingExample – Interface binding without DI frameworks
DI Integration:
- DIExample – Comprehensive DI integration showcase with advanced patterns
- ServiceLifetimes – Service lifetimes + keyed registrations with new API
- AspNetCoreExample – Web application integration
Advanced Patterns:
- FileLayering – Multiple JSON layers (deterministic last-write-wins)
- DynamicDependencies – Rules reading other config mid-recompute
- GenericProviderAPI – Full generic provider control
- StaticProviderExample – Seeding & composition with static rules
Provider Extensions:
- MicrosoftAdapterExample – Integrate any
IConfigurationSource
- HttpPollingExample – Remote polling with change detection
Deep Dive Documentation
For more in-depth documentation, see:
- Migration Guide – migrate from legacy fluent
.As<T>()
API to Binding + DI options - Architecture – execution & merge pipeline, binding system, DI integration architecture
- Binding System – interface mapping, resolution, guidelines
- Advanced Features – complete DI integration, service lifetime control, interface binding patterns
- Concepts – rules, merge semantics, binding system, auto-registration concepts
- Providers – static, file, env, HTTP, Microsoft adapter
- Examples – runnable samples
- Provider Development Guide – build your own provider
Thread Safety & Performance
- Reading config is thread-safe (atomic snapshot swap)
- Incremental recompute: only from earliest changed rule onward (prefix reused)
- Selection-hash gating: unchanged selected subtree events skipped
- Providers reused across recomputes when instance options stable
- Static rule set: rules immutable after initialization (use
UseWhen
to toggle)
Quality & Reliability
This project invests heavily in correctness-first incremental recompute. Optimisations (prefix reuse, cancellation, selection‑hash gating, debounce) are all guarded by strong differential and stress tests so performance never compromises determinism.
Core test suites (see src/tests/
):
Suite | Focus | Guarantee |
---|---|---|
DifferentialCorrectnessFuzzTests |
Random multi-provider mutation waves | Final published snapshot bit-for-bit equals a naive full merge |
PartialRecomputeTests |
Prefix reuse / earliest-index accuracy | Unchanged prefix providers are never refetched |
OverlappingRecomputeCorrectnessTests |
Cancellation under descending storms | No lost updates; latest versions survive heavy overlap |
CancellationTests |
Mid-pass abort & restart | Earlier changes preempt wasted later work |
SnapshotChangeDeletionTests |
Deletion propagation | Removed keys do not resurrect spuriously |
RecomputeStressTests |
Burst & jitter durability | Bounded passes; stable end-state |
Provider suites (Providers/*Tests ) |
Integration of file/env/http/adapter | Source-specific semantics remain correct |
Why call this out? Incremental configuration layering is deceptively complex once you introduce cancellation and reuse. Many libraries silently drop updates or leak stale keys; these suites explicitly prevent that class of regression.
Versioning & Stability
- Stable releases follow SemVer; see GitHub Releases or NuGet version history for changes.
- Breaking changes only in MAJOR versions; MINOR for additive features; PATCH for fixes.
- Provider abstractions evolve conservatively.
Packages are published under the NuGet organization cocoar.
Contributing
Issues and PRs are welcome 🎉 Keep provider abstractions stable & deterministic. Examples and docs are validated in CI.
(This README reflects the current state – future optimizations & multi-targeting will be documented in docs/
.)
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.6)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.0)
- System.Reactive (>= 6.0.1)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on Cocoar.Configuration:
Package | Downloads |
---|---|
Cocoar.Configuration.AspNetCore
Powerful layered configuration for .NET—simple, strongly typed, reactive. Compose ordered rules (file, environment, HTTP polling, static, Microsoft IConfiguration) with deterministic last-write-wins merging, partial atomic recompute, and hash-gated reactive streams. |
|
Cocoar.Configuration.MicrosoftAdapter
Powerful layered configuration for .NET—simple, strongly typed, reactive. Compose ordered rules (file, environment, HTTP polling, static, Microsoft IConfiguration) with deterministic last-write-wins merging, partial atomic recompute, and hash-gated reactive streams. |
|
Cocoar.Configuration.HttpPolling
Powerful layered configuration for .NET—simple, strongly typed, reactive. Compose ordered rules (file, environment, HTTP polling, static, Microsoft IConfiguration) with deterministic last-write-wins merging, partial atomic recompute, and hash-gated reactive streams. |
|
Cocoar.Configuration.DI
Powerful layered configuration for .NET—simple, strongly typed, reactive. Compose ordered rules (file, environment, HTTP polling, static, Microsoft IConfiguration) with deterministic last-write-wins merging, partial atomic recompute, and hash-gated reactive streams. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Initial release: lightweight, strongly-typed, deterministic multi-source configuration layering with ordered last-write-wins merge and atomic recompute.