Created
October 26, 2023 04:54
-
-
Save wipiano/c26cf0580f093bb6aae6334048be60a2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// <auto-generated/> | |
#nullable enable | |
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code. | |
namespace System.Runtime.CompilerServices | |
{ | |
using System; | |
using System.CodeDom.Compiler; | |
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "8.0.8.47906")] | |
[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.8.47906")] | |
file static class BindingExtensions | |
{ | |
#region IServiceCollection extensions. | |
/// <summary>Registers a configuration instance which TOptions will bind against.</summary> | |
[InterceptsLocation(@"C:\Users\kohe-hakoishi\source\repos\WebApplication1\WebApplication1\Program.cs", 7, 18)] | |
public static IServiceCollection Configure<TOptions>(this IServiceCollection services, IConfiguration config) where TOptions : class | |
{ | |
return Configure<TOptions>(services, string.Empty, config, configureOptions: null); | |
} | |
/// <summary>Registers a configuration instance which TOptions will bind against.</summary> | |
public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string? name, IConfiguration config, Action<BinderOptions>? configureOptions) where TOptions : class | |
{ | |
if (services is null) | |
{ | |
throw new ArgumentNullException(nameof(services)); | |
} | |
if (config is null) | |
{ | |
throw new ArgumentNullException(nameof(config)); | |
} | |
OptionsServiceCollectionExtensions.AddOptions(services); | |
services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, config)); | |
return services.AddSingleton<IConfigureOptions<TOptions>>(new ConfigureNamedOptions<TOptions>(name, instance => BindCoreMain(config, instance, typeof(TOptions), configureOptions))); | |
} | |
#endregion IServiceCollection extensions. | |
#region Core binding extensions. | |
private readonly static Lazy<HashSet<string>> s_configKeys_MyOptions = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "X" }); | |
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(MyOptions)) | |
{ | |
var temp = (MyOptions)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 MyOptions instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) | |
{ | |
ValidateConfigurationKeys(typeof(MyOptions), s_configKeys_MyOptions, configuration, binderOptions); | |
} | |
public static MyOptions InitializeMyOptions(IConfiguration configuration, BinderOptions? binderOptions) | |
{ | |
int X = default; | |
if (configuration["X"] is string value1) | |
{ | |
X = ParseInt(value1, () => configuration.GetSection("X").Path); | |
} | |
else | |
{ | |
throw new InvalidOperationException("Cannot create instance of type '<global namespace>.MyOptions' because parameter 'X' has no matching config. Each parameter in the constructor that does not have a default value must have a corresponding config entry."); | |
} | |
return new MyOptions(X) | |
{ | |
X = X, | |
}; | |
} | |
/// <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; | |
} | |
public static int ParseInt(string value, Func<string?> getPath) | |
{ | |
try | |
{ | |
return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); | |
} | |
catch (Exception exception) | |
{ | |
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); | |
} | |
} | |
#endregion Core binding extensions. | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var builder = WebApplication.CreateBuilder(args); | |
builder.Services.Configure<MyOptions>(builder.Configuration); | |
var app = builder.Build(); | |
public record MyOptions(int X); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment