Enigma.Configuration 1.0.0

dotnet add package Enigma.Configuration --version 1.0.0
                    
NuGet\Install-Package Enigma.Configuration -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Enigma.Configuration" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Enigma.Configuration" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Enigma.Configuration" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Enigma.Configuration --version 1.0.0
                    
#r "nuget: Enigma.Configuration, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Enigma.Configuration@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Enigma.Configuration&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Enigma.Configuration&version=1.0.0
                    
Install as a Cake Tool

Enigma.Configuration

NuGet License: MIT

Enigma.Configuration is typed, read/write JSON configuration for .NET — the writable alternative to Microsoft.Extensions.Configuration. The whole library follows one idiom: one JSON file ⇄ one settings class ⇄ one IConfig<T>. You write a plain settings class, bind it to a file, inject IConfig<T>, read through Value, mutate that same object, and persist it back to the very file it came from with WriteAsync. Grouping is expressed with nested C# properties, so there are no "Section:Key" strings anywhere. The library ships its own configuration model: it never touches IConfiguration, and the only Microsoft.Extensions.* package it depends on is Microsoft.Extensions.DependencyInjection.Abstractions.

What's new in 1.0 — the first release: typed binding, atomic writes, aggregated validation and DI registration with an optional start-up warm-up. See RELEASENOTES.md.

Features

  • Typed binding & registration — bind a JSON file to a settings class with AddEnigmaConfiguration(builder => builder.AddJsonFile<T>(path)), or without any container at all through EnigmaConfig.FromFile<T>(path). optional decides what a missing or empty file means, strict turns an unmapped JSON key into an error, and ConfigPaths builds per-user writable paths under the application-data folders. Registration opens no file — the path is recorded, not read.
  • Reading — the file is read lazily on the first access to Value and never again until you ask. Property matching is case-insensitive, comments and trailing commas are accepted, a UTF-8 BOM is skipped, and enums bind from their name or their number.
  • WritingWriteAsync replaces the file's content from the settings object, which is the source of truth. The write is atomic: content is staged in a temporary file next to the destination and only then put in its place, so a failed or cancelled write never leaves a corrupt file. Output is indented UTF-8 without a BOM, PascalCase as the class declares it, enums by name, and non-ASCII text unescaped so the file stays hand-editable.
  • ValidationSystem.ComponentModel.DataAnnotations attributes are always evaluated, and the walk is recursive: nested objects, list elements and dictionary entries each report the path they failed at (Smtp.Credentials.User, Servers[1].Url, Endpoints[primary].Retries). A fluent ConfigValidator<T> adds the rest — NotNull, NotEmpty, InRange, MinLength/MaxLength, Matches, Must (including cross-property conditions), each with an optional WithMessage. Failures from both halves aggregate into one ConfigurationValidationException listing every error, never just the first.
  • Dependency injection & warm-up — one IConfig<T> singleton per file, registered without touching the disk, so building a container needs no test double. The optional InitializeEnigmaConfigurationAsync loads and validates every registered file at start-up and reports all failing files at once instead of the first one.

Validated before every write

Validation runs after a load, after a reload, and before every write — so the mutation that broke the rules is caught at the point it would have been persisted, and the file on disk is left untouched. An invalid object never reaches the disk.

Installation

dotnet add package Enigma.Configuration

Targets .NET Standard 2.0, .NET 8.0, and .NET 10.0; built on Microsoft.Extensions.DependencyInjection.Abstractions 10.0.10 — the DI extension ships inside this package, so there is no separate .DependencyInjection package. That is the only runtime dependency on .NET 8.0 and .NET 10.0; on .NET Standard 2.0, where the framework does not provide them, System.Text.Json and System.ComponentModel.Annotations come along as well.

Quick start

Register a file, read a value, change it, and persist it back to the same file:

using System;
using System.ComponentModel.DataAnnotations;
using Enigma.Configuration;
using Microsoft.Extensions.DependencyInjection;

ServiceCollection services = new ServiceCollection();
services.AddEnigmaConfiguration(builder =>
    builder.AddJsonFile<AppSettings>("appsettings.json", optional: true));

IServiceProvider provider = services.BuildServiceProvider();
IConfig<AppSettings> config = provider.GetRequiredService<IConfig<AppSettings>>();

Console.WriteLine(config.Value.Smtp.Port);  // first access reads and validates the file
config.Value.Smtp.Port = 587;               // mutate the object you were handed …
await config.WriteAsync();                  // … and persist it back, atomically

public sealed class AppSettings
{
    public string ApplicationName { get; set; } = "MyApp";

    public SmtpSettings Smtp { get; set; } = new SmtpSettings();  // grouping is a nested property
}

public sealed class SmtpSettings
{
    [Required]
    public string Host { get; set; } = "localhost";

    [Range(1, 65535)]
    public int Port { get; set; } = 25;
}

Documentation

Per-category guides — each with the supported operations, the key types, and copy-pasteable C# samples verified against the public API — live under docs/guides/ in the repository, indexed by docs/guides/README.md. They cover getting started (installing, writing a settings class, registering through DI or the container-free factory, the optional and strict flags, path resolution and ConfigPaths), reading and writing (IConfig<T> in depth, lazy loading, the supported type matrix, WriteAsync and ReloadAsync semantics), validation (the DataAnnotations half and its recursive walk, the fluent ConfigValidator<T> and every built-in rule, the aggregated exception), and dependency injection (singleton semantics, generic-host wiring, composing registrations, start-up warm-up, and substituting IConfig<T> in tests).

License

Enigma.Configuration is released under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  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 is compatible.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 38 8/27/2026

First public release. Typed, read/write JSON configuration following one idiom: one JSON file bound to one settings class, exposed as a singleton IConfig<T> whose Value is read, mutated and persisted back to the same file — grouping is nested C# properties, so there are no "Section:Key" strings and IConfiguration is never touched. Lazy thread-safe loading with a forgiving reader (case-insensitive keys, comments, trailing commas, BOM, enums by name or number), atomic writes that never leave a corrupt file, explicit ReloadAsync (no hot reload in v1), always-on recursive DataAnnotations validation plus a fluent ConfigValidator<T> aggregated into a single exception and always run before a write, DI registration that opens no file, and an optional start-up warm-up reporting every failing file at once. Targets netstandard2.0, net8.0 and net10.0. See RELEASENOTES.md for the full details.