Skip to main content

Microsoft.Extensions.Configuration.Binder by Microsoft

Nuget / site data

Nuget GitHub last commit GitHub Repo stars

Details

Info

info

Name: Microsoft.Extensions.Configuration.Binder

Functionality to bind an object to data in configuration providers.

Author: Microsoft

NuGet: https://www.nuget.org/packages/Microsoft.Extensions.Configuration.Binder/

You can find more details at https://github.com/dotnet/runtime

Source : https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#configuration-binding-source-generator

Original Readme

note

About

note

Generating Binding for configuration files

How to use

Example ( source csproj, source files )

This is the CSharp Project that references Microsoft.Extensions.Configuration.Binder

<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>

<ItemGroup>
<!--<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" />-->
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<PropertyGroup>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>


</Project>

Generated Files

Those are taken from $(BaseIntermediateOutputPath)\GX

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0612, CS0618

namespace System.Runtime.CompilerServices
{
using System;
using System.CodeDom.Compiler;

[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "8.0.10.6711")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
file sealed class InterceptsLocationAttribute : Attribute
{
public InterceptsLocationAttribute(string filePath, int line, int column)
{
}
}
}

namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;

[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "8.0.10.6711")]
file static class BindingExtensions
{
#region OptionsBuilder<TOptions> extensions.
/// <summary>Registers the dependency injection container to bind <typeparamref name="TOptions"/> against the <see cref="IConfiguration"/> obtained from the DI service provider.</summary>
[InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\ConfigBinder\src\ConfigBinderDemo\Program.cs", 20, 14)]
public static OptionsBuilder<TOptions> BindConfiguration<TOptions>(this OptionsBuilder<TOptions> optionsBuilder, string configSectionPath, Action<BinderOptions>? configureBinder = null) where TOptions : class
{
if (optionsBuilder is null)
{
throw new ArgumentNullException(nameof(optionsBuilder));
}

if (configSectionPath is null)
{
throw new ArgumentNullException(nameof(configSectionPath));
}

optionsBuilder.Configure<IConfiguration>((instance, config) =>
{
if (config is null)
{
throw new ArgumentNullException(nameof(config));
}

IConfiguration section = string.Equals(string.Empty, configSectionPath, StringComparison.OrdinalIgnoreCase) ? config : config.GetSection(configSectionPath);
BindCoreMain(section, instance, typeof(TOptions), configureBinder);
});

optionsBuilder.Services.AddSingleton<IOptionsChangeTokenSource<TOptions>, ConfigurationChangeTokenSource<TOptions>>();
return optionsBuilder;
}
#endregion OptionsBuilder<TOptions> extensions.

#region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_MyAppOptions = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "AppDisplayName" });

public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action<BinderOptions>? configureOptions)
{
if (instance is null)
{
return;
}

if (!HasValueOrChildren(configuration))
{
return;
}

BinderOptions? binderOptions = GetBinderOptions(configureOptions);

if (type == typeof(global::ConfigBinderDemo.MyAppOptions))
{
var temp = (global::ConfigBinderDemo.MyAppOptions)instance;
BindCore(configuration, ref temp, defaultValueIfNotFound: false, binderOptions);
return;
}

throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}

public static void BindCore(IConfiguration configuration, ref global::ConfigBinderDemo.MyAppOptions instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
{
ValidateConfigurationKeys(typeof(global::ConfigBinderDemo.MyAppOptions), s_configKeys_MyAppOptions, configuration, binderOptions);

if (configuration["AppDisplayName"] is string value1)
{
instance.AppDisplayName = value1;
}
}


/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
if (binderOptions?.ErrorOnUnknownConfiguration is true)
{
List<string>? temp = null;

foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!keys.Value.Contains(section.Key))
{
(temp ??= new List<string>()).Add($"'{section.Key}'");
}
}

if (temp is not null)
{
throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
}
}
}

public static bool HasValueOrChildren(IConfiguration configuration)
{
if ((configuration as IConfigurationSection)?.Value is not null)
{
return true;
}
return AsConfigWithChildren(configuration) is not null;
}

public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
foreach (IConfigurationSection _ in configuration.GetChildren())
{
return configuration;
}
return null;
}

public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
{
if (configureOptions is null)
{
return null;
}

BinderOptions binderOptions = new();
configureOptions(binderOptions);

if (binderOptions.BindNonPublicProperties)
{
throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}

return binderOptions;
}
#endregion Core binding extensions.
}
}

Usefull

Download Example (.NET C# )

Share Microsoft.Extensions.Configuration.Binder

https://ignatandrei.github.io/RSCG_Examples/v2/docs/Microsoft.Extensions.Configuration.Binder

In the same category (API) - 8 other generators

MinimalApiBuilder

MinimalApis.Discovery

MinimalHelpers.Routing.Analyzers

RDG

Refit

RSCG_WebAPIExports

SafeRouting

SkinnyControllersCommon