Skip to content

existall/SimpleSettings

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

170 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ExistForAll.SimpleSettings

ExistForAll.SimpleSettings

Strongly-typed application settings for .NET. Declare a plain public interface, decorate it with defaults, and SimpleSettings binds your configuration into a runtime implementation you can inject anywhere — no concrete option classes, no per-type services.Configure<> wiring.

Installation

dotnet add package ExistForAll.SimpleSettings
dotnet add package ExistForAll.SimpleSettings.Binders
dotnet add package ExistForAll.SimpleSettings.Extensions.GenericHost
  • ExistForAll.SimpleSettings — the core binding engine and the direct SettingsBuilder API.
  • ExistForAll.SimpleSettings.Binders — additional binders (in-memory, command-line, and more).
  • ExistForAll.SimpleSettings.Extensions.GenericHost — dependency-injection integration (AddSimpleSettings).

Table of Content

  1. Getting started
  2. Building the collection
  3. Building config interfaces
  4. Default Values
  5. Build section binders
  6. Extending SimpleSettings
  7. Security & Behavior

Why SimpleSettings

.NET ships IOptions<>, but it couples your application to a framework abstraction, forces every settings shape to be a concrete class rather than an interface, and requires a manual services.Configure<> call per type. SimpleSettings keeps the positioning of IOptions<> — configuration bound into typed objects — while letting you depend on a plain interface, discovered and bound automatically, and portable across DI containers. You inject the interface; SimpleSettings supplies the implementation.

Quickstart

Declare a settings interface and bind it with the direct API:

[SettingsSection]
public interface IEmailSenderSettings
{
    [SettingsProperty(DefaultValue = "https://smtp.example.com")]
    string ServiceUrl { get; set; }

    [SettingsProperty(DefaultValue = 3)]
    int Retries { get; set; }
}

var settings = SettingsBuilder.CreateBuilder()
    .GetSettings<IEmailSenderSettings>();

Every settings interface must be public — SimpleSettings emits a runtime implementation of the interface and cannot implement a non-public one.

Feature overview

  • Bind configuration into public settings interfaces — no concrete option classes.
  • Discover settings via [SettingsSection], the ISettingsSection marker base, or a Settings name suffix.
  • Per-property defaults, key overrides, custom converters, and required-value enforcement via [SettingsProperty(...)].
  • Object-level and per-property validation through ISettingValidation<T>.
  • First-class dependency-injection integration for the .NET Generic Host.
  • Value-free exceptions on bind and conversion failures — bound values never surface in error messages (see Security & Behavior).

Dependency injection

Register SimpleSettings with the Generic Host and let it discover every settings interface in the supplied assemblies:

services.AddSimpleSettings(o =>
{
    o.AddAssemblies(new[] { typeof(IEmailSenderSettings).Assembly });
});

// after building the provider — opt-in, deferred DI validation:
serviceProvider.ValidateSimpleSettings();

ValidateSimpleSettings() extends IServiceProvider and must be called after BuildServiceProvider(); attribute and ValidatorType validators run inline during binding and need no such call. See Security & Behavior for the full validation model.

Security notes

Every exception SimpleSettings throws on a bind or conversion failure is value-free: it carries only type and property metadata and never chains an inner exception that saw the bound value, so a secret you bound cannot surface in the error's ToString() chain. This is a structural guarantee, not a convention.

There are two carve-outs the guard does not reach, and you own them: author-supplied ValidationError message text (it is emitted verbatim), and DI-resolved validator constructors (they run outside the value-free bind guard). Never echo a bound value into a validation message and never log a secret in a validator constructor. See Security & Behavior for the full treatment.

Breaking changes / migration (v1 -> v2)

The v1 -> v2 release batched four breaking changes:

  • SettingsHolder / ISettingsHolder are now internal — use the public SettingsBuilder / ISettingsCollection / ISettingsProvider surface instead.
  • The Core.AspNet package was dropped — it exposed no public type; remove any reference to it.
  • The Microsoft.Extensions.* dependency floor is now per-TFM8.0.x on net8.0, current on net10.0.
  • A public abstract SimpleSettingsException base was introduced and boundary exceptions were made public and structured; the old bare-Exception throw for a non-interface settings type is now SettingsTypeNotInterfaceException.

See the full migration guide in docs/Security.md.

About

No description or website provided.

Topics

Resources

License

Security policy

Stars

22 stars

Watchers

4 watching

Forks

Packages

 
 
 

Contributors