Atulin.ConfigBinder 0.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Atulin.ConfigBinder --version 0.2.0
                    
NuGet\Install-Package Atulin.ConfigBinder -Version 0.2.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="Atulin.ConfigBinder" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Atulin.ConfigBinder" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Atulin.ConfigBinder" />
                    
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 Atulin.ConfigBinder --version 0.2.0
                    
#r "nuget: Atulin.ConfigBinder, 0.2.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 Atulin.ConfigBinder@0.2.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=Atulin.ConfigBinder&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Atulin.ConfigBinder&version=0.2.0
                    
Install as a Cake Tool

ConfigBinder

NuGet License: MIT

ConfigBinder is a zero-reflection, highly performant configuration binding library for .NET, powered by Roslyn Source Generators. It allows you to bind strongly typed configuration classes directly from IConfiguration at compile time, eliminating the startup overhead and reflection cost associated with the built-in Microsoft.Extensions.Configuration binder.

Features

  • Zero Reflection: Uses Roslyn Source Generators to generate binding code at compile time.
  • AOT / Trimming Friendly: Completely avoids reflection, making it perfect for Native AOT and heavily trimmed applications.
  • Direct Access or IOptions: Choose between injecting your raw configuration objects directly (AddSingleton<MyConfig>) or using the standard IOptions<MyConfig> pattern.
  • Immediate.Validations Integration: Out-of-the-box support for validating configurations on startup using Immediate.Validations.
  • Custom Converters: Define property-level or global custom type converters for complex types.
  • Built-in Parsing: Automatically parses all standard primitives, enums, and any type implementing IParsable<T>.

Installation

Add the ConfigBinder package to your project. Since this is a source generator, you may want to reference it accordingly (though it provides attributes as well).

<PackageReference Include="ConfigBinder" Version="x.y.z" />

Quick Start

1. Define your Configuration Model

Decorate your configuration class, struct, or record with [ConfigSection("SectionName")]. By default, properties must have an accessible setter (or init).

using ConfigBinder.Attributes;

[ConfigSection("MyConfig")]
public sealed class MyConfig
{
    public required string Name { get; init; }
    public required int MaxRetries { get; init; }
}

2. Register Generated Configurations

In your Program.cs or startup code, call the generated extension method RegisterGeneratedConfigs on your IServiceCollection.

var builder = WebApplication.CreateBuilder(args);

// This single call registers all types decorated with [ConfigSection]
builder.Services.RegisterGeneratedConfigs(builder.Configuration);

var app = builder.Build();

// You can now resolve your config!
var config = app.Services.GetRequiredService<IOptions<MyConfig>>();

Registration Modes

ConfigBinder supports two modes for registering your configuration objects:

  • RegistrationMode.DirectAccess: Registers the object directly as a singleton (services.AddSingleton<T>).
  • RegistrationMode.Options (Default): Registers the object using the standard Options pattern (services.AddOptions<T>()).

You can override the mode on a per-class basis:

[ConfigSection("MyConfig", Mode = ConfigRegistrationMode.DirectAccess)]
public class MyOptionsConfig { /* ... */ }

Or set an assembly-wide default:

[assembly: ConfigSectionDefaults(Mode = ConfigRegistrationMode.DirectAccess)]

Custom Converters

If you need to parse complex types that don't implement IParsable<T>, you can write custom converters. A converter is simply a type with a static method (default name Convert) taking a string and a string (property name) and returning the parsed type.

Property-Level Converter

[ConfigSection("Feature")]
public class FeatureConfig
{
    [ConfigConverter(typeof(MyCustomParser), "ParseMyType")]
    public MyType SomeProperty { get; set; }
}

Global Converter

Register a converter for a specific type across your entire assembly:

[assembly: ConfigTypeConverter(typeof(MyType), typeof(MyCustomParser))]

Validation

If your project references Immediate.Validations and your configuration type implements IValidationTarget<T>, ConfigBinder will automatically wire up IValidateOptions<T> when using RegistrationMode.Options. This ensures your configuration is strictly validated on application startup.

Validation works only in RegistrationMode.Options mode.

using Immediate.Validations.Shared;

[Validate]
[ConfigSection("ValidatedConfig")]
public sealed partial class ValidatedConfig : IValidationTarget<ValidatedConfig>
{
    public required string Host { get; init; }
    public required int Port { get; init; }
}

Example

A config model like

[Validate]
[ConfigSection("Validated")]
internal sealed partial class ValidatedConfig : IValidationTarget<ValidatedConfig>
{
	[MinLength(10)]
	public required string Name { get; init; }
	public required float Weight { get; init; }
	public required DateTime BuildDate { get; init; }
}

will generate the following binding code:

internal static class ValidatedConfigConfigBinder
{
	public static ValidatedConfig Bind(IConfiguration configuration)
	{
		var section = configuration.GetSection("Validated");

		var instance = new ValidatedConfig {
			Name = ValidateString(section["Name"], "Name"),
			Weight = ParseFloat(section["Weight"], "Weight"),
			BuildDate = ParseIParsable<DateTime>(section["BuildDate"], "BuildDate"),
		};

		return instance;
	}

	private static string ValidateString(string? value, string propertyName)
	{
		if (string.IsNullOrEmpty(value))
	    {
			throw Required(propertyName);
	    }
		return value;
	}
    
	private static T ParseIParsable<T>(string? value, string propertyName) where T : IParsable<T>
	{
		if (string.IsNullOrEmpty(value))
	    {
	        throw Required(propertyName);
	    }
	    if (T.TryParse(value, CultureInfo.InvariantCulture, out var t))
	    {
	     	return t;   
	    }
	    throw BadValue(propertyName, value, typeof(T).Name);
	}
    
	private static float ParseFloat(string? value, string propertyName)
	{
	    if (string.IsNullOrEmpty(value))
	    {
	        throw Required(propertyName);
	    }
	    if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var n))
	    {
	     	return n;   
	    }
	    throw BadValue(propertyName, value, "float");
	}
    
	private static InvalidOperationException Required(string key) =>
		new($"Required configuration key '{key}' is missing or empty");
	      
	private static InvalidOperationException BadValue(string key, string? value, string type) =>
		new($"Configuration key '{key}' value '{value}' cannot be parsed as '{type}'");
}

and the following extension method:

public static class GeneratedConfigRegistration
{
	public static IServiceCollection RegisterGeneratedConfigs(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		services.AddOptions<ValidatedConfig>();
		services.AddSingleton<IOptionsFactory<ValidatedConfig>>(sp => 
			new ConfigBinderOptionsFactory<ValidatedConfig>(
				sp.GetRequiredService<IEnumerable<IConfigureOptions<ValidatedConfig>>>(),
				sp.GetRequiredService<IEnumerable<IPostConfigureOptions<ValidatedConfig>>>(),
				sp.GetRequiredService<IEnumerable<IValidateOptions<ValidatedConfig>>>(),
				_ => ValidatedConfigConfigBinder.Bind(configuration)));
		services.AddSingleton<IValidateOptions<ValidatedConfig>, ImmediateValidationOptionsValidator<ValidatedConfig>>();
		services.AddOptions<ValidatedConfig>().ValidateOnStart();

		return services;
	}
}
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 was computed.  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 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. 
.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
0.4.0 0 7/3/2026
0.3.0 45 7/1/2026
0.2.2 43 7/1/2026
0.2.1 49 7/1/2026
0.2.0 45 7/1/2026
0.1.0 46 7/1/2026