| Suppression ID | Suppressed Diagnostic ID | Description |
| :----------------------- | :----------------------- | :---------- |
| __`SYSLIBSUPPRESS0001`__ | CA1822 | Do not offer to make methods static when the methods need to be instance methods for a custom marshaller shape. |
+| __`SYSLIBSUPPRESS0002`__ | IL2026 | ConfigurationBindingGenerator: suppress RequiresUnreferencedCode diagnostic for binding call that has been intercepted by a generated static variant. |
+| __`SYSLIBSUPPRESS0003`__ | IL3050 | ConfigurationBindingGenerator: suppress RequiresDynamicCode diagnostic for binding call that has been intercepted by a generated static variant. |
<UsagePattern IdentityGlob="System.Composition*/*7.*" />
<UsagePattern IdentityGlob="Microsoft.CodeAnalysis*/*4.4.*" />
<UsagePattern IdentityGlob="Microsoft.CodeAnalysis*/*4.5.*" />
+ <UsagePattern IdentityGlob="Microsoft.CodeAnalysis*/*4.7.*" />
<!-- Allowed and pinned to major version due to https://github.com/dotnet/source-build/issues/3228 -->
<UsagePattern IdentityGlob="Microsoft.NETCore.App.Crossgen2.linux-x64/*8.*" />
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Immutable;
using System.Diagnostics;
using System.Text.RegularExpressions;
using Microsoft.CodeAnalysis;
private readonly SourceGenerationSpec _sourceGenSpec;
private bool _emitBlankLineBeforeNextStatement;
- private bool _useFullyQualifiedNames;
private int _valueSuffixIndex;
private static readonly Regex s_arrayBracketsRegex = new(Regex.Escape("[]"));
public void Emit()
{
- if (!ShouldEmitBinders())
+ if (!ShouldEmitBindingExtensions())
{
return;
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
""");
- _writer.WriteLine();
- _useFullyQualifiedNames = true;
- EmitBinder_Extensions_IConfiguration();
- EmitBinder_Extensions_OptionsBuilder();
- EmitBinder_Extensions_IServiceCollection();
+ EmitInterceptsLocationAttrDecl();
+
+ EmitStartBlock($"namespace {ProjectName}");
+ EmitUsingStatements();
+
+ _writer.WriteLine();
+ EmitStartBlock($$"""
+ {{Expression.GeneratedCodeAnnotation}}
+ file static class {{Identifier.BindingExtensions}}
+ """);
+ EmitBindingExtensions_IConfiguration();
+ EmitBindingExtensions_OptionsBuilder();
+ EmitBindingExtensions_IServiceCollection();
+ EmitCoreBindingHelpers();
+ EmitEndBlock(); // BindingExtensions class
- _useFullyQualifiedNames = false;
- Emit_CoreBindingHelper();
+ EmitEndBlock(); // Binding namespace.
- _context.AddSource($"{Identifier.GeneratedConfigurationBinder}.g.cs", _writer.ToSourceText());
+ _context.AddSource($"{Identifier.BindingExtensions}.g.cs", _writer.ToSourceText());
}
private void EmitBindCoreCall(
if (initKind is InitializationKind.AssignmentWithNullCheck)
{
Debug.Assert(!type.IsValueType);
- _writer.WriteLine($"{type.MinimalDisplayString}? {tempIdentifier} = {memberAccessExpr};");
+ _writer.WriteLine($"{type.DisplayString}? {tempIdentifier} = {memberAccessExpr};");
EmitBindCoreCall(tempIdentifier, InitializationKind.AssignmentWithNullCheck);
}
else if (initKind is InitializationKind.None && type.IsValueType)
void EmitBindCoreCall(string objExpression, InitializationKind initKind)
{
- string methodDisplayString = GetHelperMethodDisplayString(nameof(MethodsToGen_CoreBindingHelper.BindCore));
- string bindCoreCall = $@"{methodDisplayString}({configArgExpr}, ref {objExpression}, {Identifier.binderOptions});";
-
+ string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {objExpression}, {Identifier.binderOptions});";
EmitObjectInit(objExpression, initKind);
_writer.WriteLine(bindCoreCall);
writeOnSuccess?.Invoke(objExpression);
}
else if (typeKind is StringParsableTypeKind.Enum)
{
- parsedValueExpr = $"ParseEnum<{type.MinimalDisplayString}>({stringValueToParse_Expr}, () => {sectionPathExpr})";
+ parsedValueExpr = $"ParseEnum<{type.DisplayString}>({stringValueToParse_Expr}, () => {sectionPathExpr})";
}
else
{
- string helperMethodDisplayString = GetHelperMethodDisplayString(type.ParseMethodName);
- parsedValueExpr = $"{helperMethodDisplayString}({stringValueToParse_Expr}, () => {sectionPathExpr})";
+ parsedValueExpr = $"{type.ParseMethodName}({stringValueToParse_Expr}, () => {sectionPathExpr})";
}
if (!checkForNullSectionValue)
string initExpr;
CollectionSpec? collectionType = type as CollectionSpec;
- string effectiveDisplayString = GetTypeDisplayString(type);
+ string effectiveDisplayString = type.DisplayString;
if (collectionType is not null)
{
if (collectionType is EnumerableSpec { InitializationStrategy: InitializationStrategy.Array })
}
else
{
- effectiveDisplayString = GetTypeDisplayString(collectionType.ConcreteType ?? collectionType);
+ effectiveDisplayString = (collectionType.ConcreteType ?? collectionType).DisplayString;
initExpr = $"new {effectiveDisplayString}()";
}
}
return true;
}
- private void EmitCastToIConfigurationSection()
+ private void EmitInterceptsLocationAttrDecl()
{
- string sectionTypeDisplayString;
- string exceptionTypeDisplayString;
- if (_useFullyQualifiedNames)
- {
- sectionTypeDisplayString = "global::Microsoft.Extensions.Configuration.IConfigurationSection";
- exceptionTypeDisplayString = FullyQualifiedDisplayString.InvalidOperationException;
- }
- else
- {
- sectionTypeDisplayString = Identifier.IConfigurationSection;
- exceptionTypeDisplayString = nameof(InvalidOperationException);
- }
-
+ _writer.WriteLine();
_writer.WriteLine($$"""
- if ({{Identifier.configuration}} is not {{sectionTypeDisplayString}} {{Identifier.section}})
+ namespace System.Runtime.CompilerServices
{
- throw new {{exceptionTypeDisplayString}}();
+ using System;
+ using System.CodeDom.Compiler;
+
+ {{Expression.GeneratedCodeAnnotation}}
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
""");
+ _writer.WriteLine();
+ }
+
+ private void EmitUsingStatements()
+ {
+ foreach (string @namespace in _sourceGenSpec.Namespaces.ToImmutableSortedSet())
+ {
+ _writer.WriteLine($"using {@namespace};");
+ }
}
private void EmitIConfigurationHasValueOrChildrenCheck(bool voidReturn)
{
string returnPostfix = voidReturn ? string.Empty : " null";
- string methodDisplayString = GetHelperMethodDisplayString(Identifier.HasValueOrChildren);
-
_writer.WriteLine($$"""
- if (!{{methodDisplayString}}({{Identifier.configuration}}))
+ if (!{{Identifier.HasValueOrChildren}}({{Identifier.configuration}}))
{
return{{returnPostfix}};
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Operations;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
{
// List<string> is used in generated code as a temp holder for formatting
// an error for config properties that don't map to object properties.
- _sourceGenSpec.TypeNamespaces.Add("System.Collections.Generic");
+ _sourceGenSpec.Namespaces.Add("System.Collections.Generic");
spec = CreateObjectSpec(namedType);
}
string @namespace = spec.Namespace;
if (@namespace is not null and not "<global namespace>")
{
- _sourceGenSpec.TypeNamespaces.Add(@namespace);
+ _sourceGenSpec.Namespaces.Add(@namespace);
}
return _createdSpecs[type] = spec;
}
- private void RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper method, TypeSpec type)
+ private void RegisterTypeForBindCoreMainGen(TypeSpec typeSpec)
{
- if (!_sourceGenSpec.TypesForGen_CoreBindingHelper_Methods.TryGetValue(method, out HashSet<TypeSpec>? types))
+ if (typeSpec.NeedsMemberBinding)
{
- _sourceGenSpec.TypesForGen_CoreBindingHelper_Methods[method] = types = new HashSet<TypeSpec>();
+ RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCoreMain, typeSpec);
+ RegisterTypeForBindCoreGen(typeSpec);
+ _sourceGenSpec.MethodsToGen_CoreBindingHelper |= MethodsToGen_CoreBindingHelper.AsConfigWithChildren;
}
-
- types.Add(type);
- _sourceGenSpec.MethodsToGen_CoreBindingHelper |= method;
}
- private void RegisterTypeForBindCoreUntypedGen(TypeSpec typeSpec)
+ private void RegisterTypeForBindCoreGen(TypeSpec typeSpec)
{
if (typeSpec.NeedsMemberBinding)
{
RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, typeSpec);
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCoreUntyped, typeSpec);
}
}
+ private void RegisterTypeForGetCoreGen(TypeSpec typeSpec)
+ {
+ RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.GetCore, typeSpec);
+ _sourceGenSpec.MethodsToGen_CoreBindingHelper |= MethodsToGen_CoreBindingHelper.AsConfigWithChildren;
+ }
+
+ private void RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper method, TypeSpec type)
+ {
+ if (!_sourceGenSpec.TypesForGen_CoreBindingHelper_Methods.TryGetValue(method, out HashSet<TypeSpec>? types))
+ {
+ _sourceGenSpec.TypesForGen_CoreBindingHelper_Methods[method] = types = new HashSet<TypeSpec>();
+ }
+
+ types.Add(type);
+ _sourceGenSpec.MethodsToGen_CoreBindingHelper |= method;
+ }
+
+ /// <summary>
+ /// Registers interceptors for root binding methods, except for ConfigurationBinder.Bind,
+ /// which is handled by <see cref="RegisterAsInterceptor_ConfigBinder_BindMethod"/>
+ /// </summary>
+ private void RegisterAsInterceptor(Enum method, IInvocationOperation operation) =>
+ _sourceGenSpec.InterceptionInfo.RegisterCacheEntry(method, new InterceptorLocationInfo(operation));
+
private static bool IsNullable(ITypeSymbol type, [NotNullWhen(true)] out ITypeSymbol? underlyingType)
{
if (type is INamedTypeSymbol { IsGenericType: true } genericType &&
// We want a BindCore method for List<TElement> as a temp holder for the array values. We know the element type is supported.
EnumerableSpec listSpec = (GetOrCreateTypeSpec(_typeSymbols.List.Construct(arrayType.ElementType)) as EnumerableSpec)!;
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, listSpec);
+ RegisterTypeForBindCoreGen(listSpec);
EnumerableSpec spec = new EnumerableSpec(arrayType)
{
};
Debug.Assert(spec.CanInitialize);
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, spec);
+ RegisterTypeForBindCoreGen(spec);
return spec;
}
if (spec is not null)
{
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, spec);
+ RegisterTypeForBindCoreGen(spec);
spec.InitExceptionMessage ??= spec.ElementType.InitExceptionMessage;
}
constructionStrategy = InitializationStrategy.ToEnumerableMethod;
populationStrategy = CollectionPopulationStrategy.Cast_Then_Add;
toEnumerableMethodCall = "ToDictionary(pair => pair.Key, pair => pair.Value)";
- _sourceGenSpec.TypeNamespaces.Add("System.Linq");
+ _sourceGenSpec.Namespaces.Add("System.Linq");
}
else
{
if (objectSpec.NeedsMemberBinding)
{
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, objectSpec);
+ RegisterTypeForBindCoreGen(objectSpec);
}
return objectSpec;
}
}
}
+
+ public static class ParserExtensions
+ {
+ public static void RegisterCacheEntry<TKey, TValue, TEntry>(this Dictionary<TKey, TValue> cache, TKey key, TEntry entry)
+ where TKey : notnull
+ where TValue : ICollection<TEntry>, new()
+ {
+ if (!cache.TryGetValue(key, out TValue? entryCollection))
+ {
+ cache[key] = entryCollection = new TValue();
+ }
+
+ entryCollection.Add(entry);
+ }
+ }
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Operations;
+
+namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
+{
+ public sealed partial class ConfigurationBindingGenerator
+ {
+ /// <summary>
+ /// Supresses false-positive diagnostics emitted by the linker
+ /// when analyzing binding invocations that we have intercepted.
+ /// Workaround for https://github.com/dotnet/roslyn/issues/68669.
+ /// </summary>
+ [DiagnosticAnalyzer(LanguageNames.CSharp)]
+ public sealed class Suppressor : DiagnosticSuppressor
+ {
+ private const string Justification = "The target method has been intercepted by a generated static variant.";
+
+ /// <summary>
+ /// Suppression descriptor for IL2026: Members attributed with RequiresUnreferencedCode may break when trimming.
+ /// </summary>
+ private static readonly SuppressionDescriptor RUCDiagnostic = new(id: "SYSLIBSUPPRESS0002", suppressedDiagnosticId: "IL2026", Justification);
+
+ /// <summary>
+ /// Suppression descriptor for IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as native AOT.
+ /// </summary>
+ private static readonly SuppressionDescriptor RDCDiagnostic = new(id: "SYSLIBSUPPRESS0003", suppressedDiagnosticId: "IL3050", Justification);
+
+ public override ImmutableArray<SuppressionDescriptor> SupportedSuppressions => ImmutableArray.Create(RUCDiagnostic, RDCDiagnostic);
+
+ public override void ReportSuppressions(SuppressionAnalysisContext context)
+ {
+ foreach (Diagnostic diagnostic in context.ReportedDiagnostics)
+ {
+ string diagnosticId = diagnostic.Id;
+
+ if (diagnosticId != RDCDiagnostic.SuppressedDiagnosticId && diagnosticId != RUCDiagnostic.SuppressedDiagnosticId)
+ {
+ continue;
+ }
+
+ Location location = diagnostic.AdditionalLocations.Count > 0
+ ? diagnostic.AdditionalLocations[0]
+ : diagnostic.Location;
+
+ bool shouldSuppressDiagnostic =
+ location.SourceTree is SyntaxTree sourceTree &&
+ sourceTree.GetRoot().FindNode(location.SourceSpan) is SyntaxNode syntaxNode &&
+ BinderInvocation.IsCandidateSyntaxNode(syntaxNode) &&
+ context.GetSemanticModel(sourceTree)
+ .GetOperation((InvocationExpressionSyntax)syntaxNode, context.CancellationToken) is IInvocationOperation operation &&
+ BinderInvocation.IsBindingOperation(operation);
+
+ if (shouldSuppressDiagnostic)
+ {
+ SuppressionDescriptor targetSuppression = diagnosticId == RUCDiagnostic.SuppressedDiagnosticId
+ ? RUCDiagnostic
+ : RDCDiagnostic;
+ context.ReportSuppression(Suppression.Create(targetSuppression, diagnostic));
+ }
+ }
+ }
+ }
+ }
+}
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
[Generator]
public sealed partial class ConfigurationBindingGenerator : IIncrementalGenerator
{
- internal const string ProjectName = "Microsoft.Extensions.Configuration.Binder.SourceGeneration";
+ private static readonly string ProjectName = Emitter.s_assemblyName.Name;
public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.RegisterSourceOutput(inputData, (spc, source) => Execute(source.Item1, source.Item2, spc));
}
- /// <summary>
- /// Generates source code to optimize binding with ConfigurationBinder.
- /// </summary>
private static void Execute(CompilationData compilationData, ImmutableArray<BinderInvocation> inputCalls, SourceProductionContext context)
{
if (inputCalls.IsDefaultOrEmpty)
public CompilationData(CSharpCompilation compilation)
{
- LanguageVersionIsSupported = compilation.LanguageVersion >= LanguageVersion.CSharp11;
+ // We don't have a CSharp21 value available yet. Polyfill the value here for forward compat, rather than use the LangugeVersion.Preview enum value.
+ // https://github.com/dotnet/roslyn/blob/168689931cb4e3150641ec2fb188a64ce4b3b790/src/Compilers/CSharp/Portable/LanguageVersion.cs#L218-L232
+ const int LangVersion_CSharp12 = 1200;
+ LanguageVersionIsSupported = (int)compilation.LanguageVersion >= LangVersion_CSharp12;
+
if (LanguageVersionIsSupported)
{
TypeSymbols = new KnownTypeSymbols(compilation);
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using Microsoft.CodeAnalysis;
+using SourceGenerators;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
{
private bool ShouldEmitMethods(MethodsToGen_ConfigurationBinder methods) => (_sourceGenSpec.MethodsToGen_ConfigurationBinder & methods) != 0;
- private void EmitBinder_Extensions_IConfiguration()
+ private void EmitBindingExtensions_IConfiguration()
{
- Debug.Assert(_sourceGenSpec.TypesForGen_ConfigurationBinder_BindMethods.Count <= 3 &&
- !_sourceGenSpec.TypesForGen_ConfigurationBinder_BindMethods.Keys.Any(overload => (overload & MethodsToGen_ConfigurationBinder.Bind) is 0));
-
if (!ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Any))
{
return;
}
- _emitBlankLineBeforeNextStatement = false;
- EmitRootBindingClassStartBlock(Identifier.GeneratedConfigurationBinder);
-
+ EmitBindingExtStartRegion(Identifier.IConfiguration);
EmitGetMethods();
EmitGetValueMethods();
EmitBindMethods_ConfigurationBinder();
-
- EmitEndBlock();
- _emitBlankLineBeforeNextStatement = true;
+ EmitBindingExtEndRegion();
}
private void EmitGetMethods()
{
- const string expressionForGetCore = $"{FullyQualifiedDisplayString.CoreBindingHelper}.{nameof(MethodsToGen_CoreBindingHelper.GetCore)}";
+ const string expressionForGetCore = nameof(MethodsToGen_CoreBindingHelper.GetCore);
const string documentation = "Attempts to bind the configuration instance to a new instance of type T.";
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Get_T))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static T? {Identifier.Get}<T>(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.Get_T, documentation);
+ _writer.WriteLine($"public static T? {Identifier.Get}<T>(this {Identifier.IConfiguration} {Identifier.configuration}) => " +
$"(T?)({expressionForGetCore}({Identifier.configuration}, typeof(T), {Identifier.configureOptions}: null) ?? default(T));");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Get_T_BinderOptions))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static T? {Identifier.Get}<T>(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.Get_T_BinderOptions, documentation);
+ _writer.WriteLine($"public static T? {Identifier.Get}<T>(this {Identifier.IConfiguration} {Identifier.configuration}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}) => " +
$"(T?)({expressionForGetCore}({Identifier.configuration}, typeof(T), {Identifier.configureOptions}) ?? default(T));");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Get_TypeOf))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static object? {Identifier.Get}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayString.Type} {Identifier.type}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.Get_TypeOf, documentation);
+ _writer.WriteLine($"public static object? {Identifier.Get}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}) => " +
$"{expressionForGetCore}({Identifier.configuration}, {Identifier.type}, {Identifier.configureOptions}: null);");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Get_TypeOf_BinderOptions))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static object? {Identifier.Get}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayString.Type} {Identifier.type}, {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.Get_TypeOf_BinderOptions, documentation);
+ _writer.WriteLine($"public static object? {Identifier.Get}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}) => " +
$"{expressionForGetCore}({Identifier.configuration}, {Identifier.type}, {Identifier.configureOptions});");
}
}
private void EmitGetValueMethods()
{
- const string expressionForGetValueCore = $"{FullyQualifiedDisplayString.CoreBindingHelper}.{nameof(MethodsToGen_CoreBindingHelper.GetValueCore)}";
+ const string expressionForGetValueCore = $"{Identifier.BindingExtensions}.{nameof(MethodsToGen_CoreBindingHelper.GetValueCore)}";
const string documentation = "Extracts the value with the specified key and converts it to the specified type.";
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.GetValue_T_key))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static T? {Identifier.GetValue}<T>(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, string {Identifier.key}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.GetValue_T_key, documentation);
+ _writer.WriteLine($"public static T? {Identifier.GetValue}<T>(this {Identifier.IConfiguration} {Identifier.configuration}, string {Identifier.key}) => " +
$"(T?)({expressionForGetValueCore}({Identifier.configuration}, typeof(T), {Identifier.key}) ?? default(T));");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.GetValue_T_key_defaultValue))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static T? {Identifier.GetValue}<T>(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, string {Identifier.key}, T {Identifier.defaultValue}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.GetValue_T_key_defaultValue, documentation);
+ _writer.WriteLine($"public static T? {Identifier.GetValue}<T>(this {Identifier.IConfiguration} {Identifier.configuration}, string {Identifier.key}, T {Identifier.defaultValue}) => " +
$"(T?)({expressionForGetValueCore}({Identifier.configuration}, typeof(T), {Identifier.key}) ?? {Identifier.defaultValue});");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.GetValue_TypeOf_key))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static object? {Identifier.GetValue}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayString.Type} {Identifier.type}, string {Identifier.key}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.GetValue_TypeOf_key, documentation);
+ _writer.WriteLine($"public static object? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, string {Identifier.key}) => " +
$"{expressionForGetValueCore}({Identifier.configuration}, {Identifier.type}, {Identifier.key});");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.GetValue_TypeOf_key_defaultValue))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static object? {Identifier.GetValue}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayString.Type} {Identifier.type}, string {Identifier.key}, object? {Identifier.defaultValue}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.GetValue_TypeOf_key_defaultValue, documentation);
+ _writer.WriteLine($"public static object? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, string {Identifier.key}, object? {Identifier.defaultValue}) => " +
$"{expressionForGetValueCore}({Identifier.configuration}, {Identifier.type}, {Identifier.key}) ?? {Identifier.defaultValue};");
}
}
return;
}
- Dictionary<MethodsToGen_ConfigurationBinder, HashSet<TypeSpec>> types = _sourceGenSpec.TypesForGen_ConfigurationBinder_BindMethods;
+ string objParamExpr = $"object? {Identifier.obj}";
- if (types.TryGetValue(MethodsToGen_ConfigurationBinder.Bind_instance, out HashSet<TypeSpec>? typeSpecs))
+ if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Bind_instance))
{
- foreach (TypeSpec type in typeSpecs)
- {
- EmitMethodImplementation(
- type,
- additionalParams: GetObjParameter(type),
- configExpression: Identifier.configuration,
- configureOptions: false);
- }
+ EmitMethods(
+ MethodsToGen_ConfigurationBinder.Bind_instance,
+ additionalParams: objParamExpr,
+ configExpression: Identifier.configuration,
+ configureOptions: false);
}
- if (types.TryGetValue(MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions, out typeSpecs))
+ if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions))
{
- foreach (TypeSpec type in typeSpecs)
- {
- EmitMethodImplementation(
- type,
- additionalParams: $"{GetObjParameter(type)}, {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}",
- configExpression: Identifier.configuration,
- configureOptions: true);
- }
+ EmitMethods(
+ MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions,
+ additionalParams: $"{objParamExpr}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}",
+ configExpression: Identifier.configuration,
+ configureOptions: true);
}
- if (types.TryGetValue(MethodsToGen_ConfigurationBinder.Bind_key_instance, out typeSpecs))
+ if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Bind_key_instance))
{
- foreach (TypeSpec type in typeSpecs)
- {
- EmitMethodImplementation(
- type,
- additionalParams: $"string {Identifier.key}, {GetObjParameter(type)}",
- configExpression: $"{Expression.configurationGetSection}({Identifier.key})",
- configureOptions: false);
- }
+ EmitMethods(
+ MethodsToGen_ConfigurationBinder.Bind_key_instance,
+ additionalParams: $"string {Identifier.key}, {objParamExpr}",
+ configExpression: $"{Expression.configurationGetSection}({Identifier.key})",
+ configureOptions: false);
}
- void EmitMethodImplementation(TypeSpec type, string additionalParams, string configExpression, bool configureOptions)
+ void EmitMethods(MethodsToGen_ConfigurationBinder method, string additionalParams, string configExpression, bool configureOptions)
{
- string binderOptionsArg = configureOptions ? $"{Expression.GetBinderOptions}({Identifier.configureOptions})" : $"{Identifier.binderOptions}: null";
-
- string returnExpression;
- if (type.CanInitialize)
+ foreach (KeyValuePair<TypeSpec, List<InterceptorLocationInfo>> pair in _sourceGenSpec.InterceptionInfo_ConfigBinder.GetOverloadInfo(method))
{
- returnExpression = type.NeedsMemberBinding
- ? $"{FullyQualifiedDisplayString.CoreBindingHelper}.{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configExpression}, ref {Identifier.obj}, {binderOptionsArg})"
- : "{ }";
+ (TypeSpec type, List<InterceptorLocationInfo> interceptorInfoList) = (pair.Key, pair.Value);
+
+ EmitBlankLineIfRequired();
+ _writer.WriteLine($"/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>");
+ EmitInterceptsLocationAnnotations(interceptorInfoList);
+ EmitStartBlock($"public static void {Identifier.Bind}_{type.DisplayString.ToIdentifierSubstring()}(this {Identifier.IConfiguration} {Identifier.configuration}, {additionalParams})");
+
+ if (!EmitInitException(type) && type.NeedsMemberBinding)
+ {
+ string binderOptionsArg = configureOptions ? $"{Identifier.GetBinderOptions}({Identifier.configureOptions})" : $"{Identifier.binderOptions}: null";
+
+ EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
+ if (!type.IsValueType)
+ {
+ EmitCheckForNullArgument_WithBlankLine(Identifier.obj);
+ }
+ _writer.WriteLine($$"""
+ var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.obj}};
+ {{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, {{binderOptionsArg}});
+ """);
+ }
+
+ EmitEndBlock();
}
- else
- {
- returnExpression = GetInitException(type.InitExceptionMessage);
- }
-
- StartMethodDefinition("Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.");
- _writer.WriteLine($"public static void {Identifier.Bind}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {additionalParams}) => "
- + $"{returnExpression};");
}
-
- string GetObjParameter(TypeSpec type) => $"{type.FullyQualifiedDisplayString} {Identifier.obj}";
}
- private void StartMethodDefinition(string documentation)
+ private void StartMethodDefinition(MethodsToGen_ConfigurationBinder method, string documentation)
{
EmitBlankLineIfRequired();
_writer.WriteLine($"/// <summary>{documentation}</summary>");
+ EmitInterceptsLocationAnnotations(method);
}
}
}
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis;
+using SourceGenerators;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
{
private bool ShouldEmitMethods(MethodsToGen_CoreBindingHelper methods) => (_sourceGenSpec.MethodsToGen_CoreBindingHelper & methods) != 0;
- private void Emit_CoreBindingHelper()
+ private void EmitCoreBindingHelpers()
{
Debug.Assert(_emitBlankLineBeforeNextStatement);
- _writer.WriteLine();
- _emitBlankLineBeforeNextStatement = false;
-
- EmitStartBlock($"namespace {ProjectName}");
- EmitHelperUsingStatements();
-
- _writer.WriteLine();
-
- EmitStartBlock($$"""
- /// <summary>Provide core binding logic.</summary>
- {{GetGeneratedCodeAttributeSrc()}}
- file static class {{Identifier.CoreBindingHelper}}
- """);
-
+ EmitBindingExtStartRegion("Core binding");
EmitConfigurationKeyCaches();
EmitGetCoreMethod();
EmitGetValueCoreMethod();
- EmitBindCoreUntypedMethod();
+ EmitBindCoreMainMethod();
EmitBindCoreMethods();
EmitInitializeMethods();
EmitHelperMethods();
-
- EmitEndBlock(); // End helper class.
- EmitEndBlock(); // End namespace.
- }
-
- private void EmitHelperUsingStatements()
- {
- foreach (string @namespace in _sourceGenSpec.TypeNamespaces.ToImmutableSortedSet())
- {
- _writer.WriteLine($"using {@namespace};");
- }
+ EmitBindingExtEndRegion();
}
private void EmitConfigurationKeyCaches()
return;
}
+ EmitBlankLineIfRequired();
+
foreach (TypeSpec type in targetTypes)
{
if (type is not ObjectSpec objectType)
string configKeysSource = string.Join(", ", keys);
string fieldName = GetConfigKeyCacheFieldName(objectType);
- _writer.WriteLine($@"private readonly static Lazy<{MinimalDisplayString.HashSetOfString}> {fieldName} = new(() => new {MinimalDisplayString.HashSetOfString}(StringComparer.OrdinalIgnoreCase) {{ {configKeysSource} }});");
+ _writer.WriteLine($@"private readonly static Lazy<{TypeDisplayString.HashSetOfString}> {fieldName} = new(() => new {TypeDisplayString.HashSetOfString}(StringComparer.OrdinalIgnoreCase) {{ {configKeysSource} }});");
}
-
- _emitBlankLineBeforeNextStatement = true;
}
private void EmitGetCoreMethod()
EmitIConfigurationHasValueOrChildrenCheck(voidReturn: false);
+ bool isFirstType = true;
foreach (TypeSpec type in types)
{
TypeSpec effectiveType = type.EffectiveType;
TypeSpecKind kind = effectiveType.SpecKind;
+ string conditionKindExpr = GetConditionKindExpr(ref isFirstType);
- EmitStartBlock($"if (type == typeof({type.MinimalDisplayString}))");
+ EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
if (effectiveType is ParsableFromStringSpec stringParsableType)
{
- EmitCastToIConfigurationSection();
+ _writer.WriteLine($$"""
+ if ({{Identifier.configuration}} is not {{Identifier.IConfigurationSection}} {{Identifier.section}})
+ {
+ throw new {{Identifier.InvalidOperationException}}();
+ }
+ """);
+
EmitBindLogicFromString(
stringParsableType,
Expression.sectionValue,
}
EmitEndBlock();
- _writer.WriteLine();
}
+ _writer.WriteLine();
Emit_NotSupportedException_TypeNotDetectedAsInput();
EmitEndBlock();
_emitBlankLineBeforeNextStatement = true;
_writer.WriteLine();
+ bool isFirstType = true;
foreach (TypeSpec type in targetTypes)
{
- EmitStartBlock($"if ({Identifier.type} == typeof({type.MinimalDisplayString}))");
+ string conditionKindExpr = GetConditionKindExpr(ref isFirstType);
+ EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
EmitBindLogicFromString(
(ParsableFromStringSpec)type.EffectiveType,
useIncrementalStringValueIdentifier: false);
EmitEndBlock();
- _writer.WriteLine();
}
+ _writer.WriteLine();
_writer.WriteLine("return null;");
EmitEndBlock();
_emitBlankLineBeforeNextStatement = true;
}
- private void EmitBindCoreUntypedMethod()
+ private void EmitBindCoreMainMethod()
{
- if (!_sourceGenSpec.TypesForGen_CoreBindingHelper_Methods.TryGetValue(MethodsToGen_CoreBindingHelper.BindCoreUntyped, out HashSet<TypeSpec>? targetTypes))
+ if (!_sourceGenSpec.TypesForGen_CoreBindingHelper_Methods.TryGetValue(MethodsToGen_CoreBindingHelper.BindCoreMain, out HashSet<TypeSpec>? targetTypes))
{
return;
}
EmitBlankLineIfRequired();
-
- EmitStartBlock($"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCoreUntyped)}(this {Identifier.IConfiguration} {Identifier.configuration}, object {Identifier.obj}, Type {Identifier.type}, {MinimalDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions})");
-
+ EmitStartBlock($"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCoreMain)}({Identifier.IConfiguration} {Identifier.configuration}, object {Identifier.obj}, Type {Identifier.type}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions})");
EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
-
+ EmitCheckForNullArgument_WithBlankLine(Identifier.obj);
+ EmitIConfigurationHasValueOrChildrenCheck(voidReturn: true);
_writer.WriteLine($"{Identifier.BinderOptions}? {Identifier.binderOptions} = {Identifier.GetBinderOptions}({Identifier.configureOptions});");
_writer.WriteLine();
- EmitIConfigurationHasValueOrChildrenCheck(voidReturn: true);
-
+ bool isFirstType = true;
foreach (TypeSpec type in targetTypes)
{
- EmitStartBlock($"if (type == typeof({type.MinimalDisplayString}))");
-
TypeSpec effectiveType = type.EffectiveType;
+ string conditionKindExpr = GetConditionKindExpr(ref isFirstType);
+
+ EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
if (!EmitInitException(effectiveType))
{
- _writer.WriteLine($"var {Identifier.temp} = ({effectiveType.MinimalDisplayString}){Identifier.obj};");
+ _writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.obj};");
EmitBindCoreCall(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
_writer.WriteLine($"return;");
}
-
EmitEndBlock();
- _writer.WriteLine();
}
+ _writer.WriteLine();
Emit_NotSupportedException_TypeNotDetectedAsInput();
EmitEndBlock();
- _emitBlankLineBeforeNextStatement = true;
}
private void EmitBindCoreMethods()
{
Debug.Assert(type.CanInitialize);
- string objParameterExpression = $"ref {type.MinimalDisplayString} {Identifier.obj}";
+ string objParameterExpression = $"ref {type.DisplayString} {Identifier.obj}";
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
- EmitCheckForNullArgument_WithBlankLine_IfRequired(type.IsValueType);
-
TypeSpec effectiveType = type.EffectiveType;
if (effectiveType is EnumerableSpec enumerable)
{
List<ParameterSpec> ctorParams = type.ConstructorParameters;
IEnumerable<PropertySpec> initOnlyProps = type.Properties.Values.Where(prop => prop is { SetOnInit: true });
List<string> ctorArgList = new();
- string displayString = type.MinimalDisplayString;
+ string displayString = type.DisplayString;
- EmitStartBlock($"public static {type.MinimalDisplayString} {GetInitalizeMethodDisplayString(type)}({Identifier.IConfiguration} {Identifier.configuration}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
+ EmitStartBlock($"public static {type.DisplayString} {GetInitalizeMethodDisplayString(type)}({Identifier.IConfiguration} {Identifier.configuration}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
_emitBlankLineBeforeNextStatement = false;
foreach (ParameterSpec parameter in ctorParams)
TypeSpec memberType = member.Type;
bool errorOnFailedBinding = member.ErrorOnFailedBinding;
- string parsedMemberIdentifierDeclarationPrefix = $"{memberType.MinimalDisplayString} {member.Name}";
+ string parsedMemberIdentifierDeclarationPrefix = $"{memberType.DisplayString} {member.Name}";
string parsedMemberIdentifier;
if (memberType is ParsableFromStringSpec { StringParsableTypeKind: StringParsableTypeKind.AssignFromSectionValue })
if (errorOnFailedBinding)
{
- string condition = $@" if ({Identifier.configuration}[""{member.ConfigurationKeyName}""] is not {memberType.MinimalDisplayString} {member.Name})";
+ string condition = $@" if ({Identifier.configuration}[""{member.ConfigurationKeyName}""] is not {memberType.DisplayString} {member.Name})";
EmitThrowBlock(condition);
_writer.WriteLine();
return;
_writer.WriteLine($$"""
{{condition}}
{
- throw new {{GetInvalidOperationDisplayName()}}("{{string.Format(ExceptionMessages.ParameterHasNoMatchingConfig, type.Name, member.Name)}}");
+ throw new {{Identifier.InvalidOperationException}}("{{string.Format(ExceptionMessages.ParameterHasNoMatchingConfig, type.Name, member.Name)}}");
}
""");
}
}
+
private void EmitHelperMethods()
{
+ // Emitted if we are to bind objects with complex members, or if we're emitting BindCoreMain or GetCore methods.
+ bool emitAsConfigWithChildren = ShouldEmitMethods(MethodsToGen_CoreBindingHelper.AsConfigWithChildren);
+
if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.BindCore))
{
+ EmitBlankLineIfRequired();
EmitValidateConfigurationKeysMethod();
}
- if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.BindCoreUntyped | MethodsToGen_CoreBindingHelper.GetCore))
+ if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.BindCoreMain | MethodsToGen_CoreBindingHelper.GetCore))
{
- _writer.WriteLine();
+ // HasValueOrChildren references this method.
+ Debug.Assert(emitAsConfigWithChildren);
+ EmitBlankLineIfRequired();
EmitHasValueOrChildrenMethod();
- _writer.WriteLine();
- EmitAsConfigWithChildrenMethod();
- _emitBlankLineBeforeNextStatement = true;
}
- else if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.AsConfigWithChildren))
+
+ if (emitAsConfigWithChildren)
{
- _writer.WriteLine();
+ EmitBlankLineIfRequired();
EmitAsConfigWithChildrenMethod();
- _emitBlankLineBeforeNextStatement = true;
}
- if (ShouldEmitMethods(
- MethodsToGen_CoreBindingHelper.BindCoreUntyped | MethodsToGen_CoreBindingHelper.GetCore) ||
+ if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.BindCoreMain | MethodsToGen_CoreBindingHelper.GetCore) ||
ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions))
{
- _writer.WriteLine();
+ EmitBlankLineIfRequired();
EmitGetBinderOptionsHelper();
- _emitBlankLineBeforeNextStatement = true;
}
bool enumTypeExists = false;
EmitBlankLineIfRequired();
_writer.WriteLine($$"""
/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
- public static void {{Identifier.ValidateConfigurationKeys}}(Type {{Identifier.type}}, {{MinimalDisplayString.LazyHashSetOfString}} {{keysIdentifier}}, {{Identifier.IConfiguration}} {{Identifier.configuration}}, {{Identifier.BinderOptions}}? {{Identifier.binderOptions}})
+ public static void {{Identifier.ValidateConfigurationKeys}}(Type {{Identifier.type}}, {{TypeDisplayString.LazyHashSetOfString}} {{keysIdentifier}}, {{Identifier.IConfiguration}} {{Identifier.configuration}}, {{Identifier.BinderOptions}}? {{Identifier.binderOptions}})
{
if ({{Identifier.binderOptions}}?.{{Identifier.ErrorOnUnknownConfiguration}} is true)
{
- {{MinimalDisplayString.ListOfString}}? {{Identifier.temp}} = null;
+ {{TypeDisplayString.ListOfString}}? {{Identifier.temp}} = null;
foreach ({{Identifier.IConfigurationSection}} {{Identifier.section}} in {{Identifier.configuration}}.{{Identifier.GetChildren}}())
{
if (!{{keysIdentifier}}.Value.Contains({{Expression.sectionKey}}))
{
- ({{Identifier.temp}} ??= new {{MinimalDisplayString.ListOfString}}()).Add($"'{{{Expression.sectionKey}}}'");
+ ({{Identifier.temp}} ??= new {{TypeDisplayString.ListOfString}}()).Add($"'{{{Expression.sectionKey}}}'");
}
}
{
return true;
}
- return {{Identifier.AsConfigWithChildren}}({{Identifier.configuration}}) is not null;
+ return {{MethodsToGen_CoreBindingHelper.AsConfigWithChildren}}({{Identifier.configuration}}) is not null;
}
""");
}
private void EmitAsConfigWithChildrenMethod()
{
_writer.WriteLine($$"""
- public static {{Identifier.IConfiguration}}? {{Identifier.AsConfigWithChildren}}({{Identifier.IConfiguration}} {{Identifier.configuration}})
+ public static {{Identifier.IConfiguration}}? {{MethodsToGen_CoreBindingHelper.AsConfigWithChildren}}({{Identifier.IConfiguration}} {{Identifier.configuration}})
{
foreach ({{Identifier.IConfigurationSection}} _ in {{Identifier.configuration}}.{{Identifier.GetChildren}}())
{
private void EmitGetBinderOptionsHelper()
{
_writer.WriteLine($$"""
- public static {{Identifier.BinderOptions}}? {{Identifier.GetBinderOptions}}({{MinimalDisplayString.NullableActionOfBinderOptions}} {{Identifier.configureOptions}})
+ public static {{Identifier.BinderOptions}}? {{Identifier.GetBinderOptions}}({{TypeDisplayString.NullableActionOfBinderOptions}} {{Identifier.configureOptions}})
{
if ({{Identifier.configureOptions}} is null)
{
if ({{Identifier.binderOptions}}.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"{{string.Format(ExceptionMessages.CannotSpecifyBindNonPublicProperties)}}");
+ throw new NotSupportedException($"{{string.Format(ExceptionMessages.CannotSpecifyBindNonPublicProperties)}}");
}
return {{Identifier.binderOptions}};
private void EmitEnumParseMethod()
{
- string innerExceptionTypeDisplayString = _useFullyQualifiedNames ? "global::System.Exception" : "Exception";
string exceptionArg1 = string.Format(ExceptionMessages.FailedBinding, $"{{{Identifier.getPath}()}}", $"{{typeof(T)}}");
_writer.WriteLine($$"""
return Enum.Parse<T>(value, ignoreCase: true);
#endif
}
- catch ({{innerExceptionTypeDisplayString}} {{Identifier.exception}})
+ catch ({{Identifier.Exception}} {{Identifier.exception}})
{
- throw new {{GetInvalidOperationDisplayName()}}($"{{exceptionArg1}}", {{Identifier.exception}});
+ throw new {{Identifier.InvalidOperationException}}($"{{exceptionArg1}}", {{Identifier.exception}});
}
}
""");
private void EmitPrimitiveParseMethod(ParsableFromStringSpec type)
{
- string innerExceptionTypeDisplayString;
- string cultureInfoTypeDisplayString;
- string numberStylesTypeDisplayString;
-
- if (_useFullyQualifiedNames)
- {
- innerExceptionTypeDisplayString = "global::System.Exception";
- cultureInfoTypeDisplayString = "global::System.Globalization.CultureInfo";
- numberStylesTypeDisplayString = "global::System.Globalization.NumberStyles";
- }
- else
- {
- innerExceptionTypeDisplayString = "Exception";
- cultureInfoTypeDisplayString = "CultureInfo";
- numberStylesTypeDisplayString = "NumberStyles";
- }
-
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
- string typeDisplayString = type.MinimalDisplayString;
-
- string invariantCultureExpression = $"{cultureInfoTypeDisplayString}.InvariantCulture";
+ string typeDisplayString = type.DisplayString;
+ string invariantCultureExpression = $"{Identifier.CultureInfo}.InvariantCulture";
string parsedValueExpr;
+
switch (typeKind)
{
case StringParsableTypeKind.Enum:
break;
case StringParsableTypeKind.Integer:
{
- parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {numberStylesTypeDisplayString}.Integer, {invariantCultureExpression})";
+ parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {Identifier.NumberStyles}.Integer, {invariantCultureExpression})";
}
break;
case StringParsableTypeKind.Float:
{
- parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {numberStylesTypeDisplayString}.Float, {invariantCultureExpression})";
+ parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {Identifier.NumberStyles}.Float, {invariantCultureExpression})";
}
break;
case StringParsableTypeKind.Parse:
break;
case StringParsableTypeKind.CultureInfo:
{
- parsedValueExpr = $"{cultureInfoTypeDisplayString}.GetCultureInfo({Identifier.value})";
+ parsedValueExpr = $"{Identifier.CultureInfo}.GetCultureInfo({Identifier.value})";
}
break;
case StringParsableTypeKind.Uri:
{
return {{parsedValueExpr}};
}
- catch ({{innerExceptionTypeDisplayString}} {{Identifier.exception}})
+ catch ({{Identifier.Exception}} {{Identifier.exception}})
{
- throw new {{GetInvalidOperationDisplayName()}}($"{{exceptionArg1}}", {{Identifier.exception}});
+ throw new {{Identifier.InvalidOperationException}}($"{{exceptionArg1}}", {{Identifier.exception}});
}
""");
}
if (keyType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue)
{
// Save value to local to avoid parsing twice - during look-up and during add.
- _writer.WriteLine($"{keyType.MinimalDisplayString} {Identifier.key} = {parsedKeyExpr};");
+ _writer.WriteLine($"{keyType.DisplayString} {Identifier.key} = {parsedKeyExpr};");
parsedKeyExpr = Identifier.key;
}
bool isValueType = elementType.IsValueType;
string expressionForElementIsNotNull = $"{Identifier.element} is not null";
- string elementTypeDisplayString = elementType.MinimalDisplayString + (elementType.IsValueType ? string.Empty : "?");
+ string elementTypeDisplayString = elementType.DisplayString + (elementType.IsValueType ? string.Empty : "?");
string expressionForElementExists = $"{objIdentifier}.{Identifier.TryGetValue}({parsedKeyExpr}, out {elementTypeDisplayString} {Identifier.element})";
string conditionToUseExistingElement = expressionForElementExists;
// we need to copy its contents into a new instance & then append/bind to that.
string initExpression = collectionSpec.InitializationStrategy is InitializationStrategy.ParameterizedConstructor
- ? $"new {collectionSpec.ConcreteType.MinimalDisplayString}({Identifier.element})"
+ ? $"new {collectionSpec.ConcreteType.DisplayString}({Identifier.element})"
: $"{Identifier.element}.{collectionSpec.ToEnumerableMethodCall!}";
_writer.WriteLine($$"""
Debug.Assert(type.NeedsMemberBinding);
string keyCacheFieldName = GetConfigKeyCacheFieldName(type);
- string validateMethodCallExpr = $"{Identifier.ValidateConfigurationKeys}(typeof({type.MinimalDisplayString}), {keyCacheFieldName}, {Identifier.configuration}, {Identifier.binderOptions});";
+ string validateMethodCallExpr = $"{Identifier.ValidateConfigurationKeys}(typeof({type.DisplayString}), {keyCacheFieldName}, {Identifier.configuration}, {Identifier.binderOptions});";
_writer.WriteLine(validateMethodCallExpr);
foreach (PropertySpec property in type.Properties.Values)
bool noSetter_And_IsReadonly = !property.CanSet && property.Type is CollectionSpec { InitializationStrategy: InitializationStrategy.ParameterizedConstructor };
if (property.ShouldBind() && !noSetter_And_IsReadonly)
{
- string containingTypeRef = property.IsStatic ? type.MinimalDisplayString : Identifier.obj;
+ string containingTypeRef = property.IsStatic ? type.DisplayString : Identifier.obj;
EmitBindImplForMember(
property,
memberAccessExpr: $"{containingTypeRef}.{property.Name}",
return true;
}
- string sectionValidationCall = $"{Identifier.AsConfigWithChildren}({sectionParseExpr})";
+ string sectionValidationCall = $"{MethodsToGen_CoreBindingHelper.AsConfigWithChildren}({sectionParseExpr})";
string sectionIdentifier = GetIncrementalIdentifier(Identifier.section);
EmitStartBlock($"if ({sectionValidationCall} is {Identifier.IConfigurationSection} {sectionIdentifier})");
}
Debug.Assert(canSet);
- string effectiveMemberTypeDisplayString = effectiveMemberType.MinimalDisplayString;
+ string effectiveMemberTypeDisplayString = effectiveMemberType.DisplayString;
initKind = InitializationKind.None;
if (memberType.SpecKind is TypeSpecKind.Nullable)
{
string nullableTempIdentifier = GetIncrementalIdentifier(Identifier.temp);
- _writer.WriteLine($"{memberType.MinimalDisplayString} {nullableTempIdentifier} = {memberAccessExpr};");
+ _writer.WriteLine($"{memberType.DisplayString} {nullableTempIdentifier} = {memberAccessExpr};");
_writer.WriteLine(
$"{effectiveMemberTypeDisplayString} {tempIdentifier} = {nullableTempIdentifier}.{Identifier.HasValue} ? {nullableTempIdentifier}.{Identifier.Value} : new {effectiveMemberTypeDisplayString}();");
{
objIdentifier = Identifier.temp;
_writer.WriteLine($$"""
- if ({{Identifier.obj}} is not {{type.PopulationCastType!.MinimalDisplayString}} {{objIdentifier}})
+ if ({{Identifier.obj}} is not {{type.PopulationCastType!.DisplayString}} {{objIdentifier}})
{
return;
}
private void Emit_Foreach_Section_In_ConfigChildren_StartBlock() =>
EmitStartBlock($"foreach ({Identifier.IConfigurationSection} {Identifier.section} in {Identifier.configuration}.{Identifier.GetChildren}())");
+ private void Emit_NotSupportedException_TypeNotDetectedAsInput() =>
+ _writer.WriteLine(@$"throw new NotSupportedException($""{string.Format(ExceptionMessages.TypeNotDetectedAsInput, "{type}")}"");");
+
private static string GetSectionPathFromConfigurationExpression(string configurationKeyName)
=> $@"{GetSectionFromConfigurationExpression(configurationKeyName)}.{Identifier.Path}";
private static string GetSectionFromConfigurationExpression(string configurationKeyName, bool addQuotes = true)
{
string argExpr = addQuotes ? $@"""{configurationKeyName}""" : configurationKeyName;
- return $@"{Expression.configurationGetSection}({argExpr})";
+ return $@"{Identifier.configuration}.{Identifier.GetSection}({argExpr})";
}
- private static string GetConfigKeyCacheFieldName(ObjectSpec type) =>
- $"s_configKeys_{type.DisplayStringWithoutSpecialCharacters}";
+ private static string GetConditionKindExpr(ref bool isFirstType)
+ {
+ if (isFirstType)
+ {
+ isFirstType = false;
+ return "if";
+ }
- private void Emit_NotSupportedException_TypeNotDetectedAsInput() =>
- _writer.WriteLine(@$"throw new global::System.NotSupportedException($""{string.Format(ExceptionMessages.TypeNotDetectedAsInput, "{type}")}"");");
+ return "else if";
+ }
+
+ private static string GetConfigKeyCacheFieldName(ObjectSpec type) =>
+ $"s_configKeys_{type.DisplayString.ToIdentifierSubstring()}";
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
{
private sealed partial class Emitter
{
- private static readonly AssemblyName s_assemblyName = typeof(Emitter).Assembly.GetName();
+ private string? _emittedExtsTargetType;
+
+ internal static readonly AssemblyName s_assemblyName = typeof(ConfigurationBindingGenerator).Assembly.GetName();
private enum InitializationKind
{
public const string sectionPath = "section.Path";
public const string sectionValue = "section.Value";
- public const string GetBinderOptions = $"{FullyQualifiedDisplayString.CoreBindingHelper}.{Identifier.GetBinderOptions}";
- }
-
- private static class FullyQualifiedDisplayString
- {
- public const string ActionOfBinderOptions = $"global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>";
- public const string AddSingleton = $"{ServiceCollectionServiceExtensions}.AddSingleton";
- public const string ConfigurationChangeTokenSource = "global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource";
- public const string CoreBindingHelper = $"global::{ProjectName}.{Identifier.CoreBindingHelper}";
- public const string IConfiguration = "global::Microsoft.Extensions.Configuration.IConfiguration";
- public const string IConfigurationSection = IConfiguration + "Section";
- public const string IOptionsChangeTokenSource = "global::Microsoft.Extensions.Options.IOptionsChangeTokenSource";
- public const string InvalidOperationException = "global::System.InvalidOperationException";
- public const string IServiceCollection = "global::Microsoft.Extensions.DependencyInjection.IServiceCollection";
- public const string NotSupportedException = "global::System.NotSupportedException";
- public const string OptionsBuilderOfTOptions = $"global::Microsoft.Extensions.Options.OptionsBuilder<{Identifier.TOptions}>";
- public const string ServiceCollectionServiceExtensions = "global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions";
- public const string Type = $"global::System.Type";
+ public static string GeneratedCodeAnnotation = $@"[GeneratedCode(""{s_assemblyName.Name}"", ""{s_assemblyName.Version}"")]";
}
- private static class MinimalDisplayString
+ private static class TypeDisplayString
{
public const string NullableActionOfBinderOptions = "Action<BinderOptions>?";
+ public const string OptionsBuilderOfTOptions = $"OptionsBuilder<{Identifier.TOptions}>";
public const string HashSetOfString = "HashSet<string>";
public const string LazyHashSetOfString = "Lazy<HashSet<string>>";
public const string ListOfString = "List<string>";
public const string services = nameof(services);
public const string temp = nameof(temp);
public const string type = nameof(type);
+ public const string typedObj = nameof(typedObj);
public const string validateKeys = nameof(validateKeys);
public const string value = nameof(value);
public const string AddSingleton = nameof(AddSingleton);
public const string Any = nameof(Any);
public const string Array = nameof(Array);
- public const string AsConfigWithChildren = nameof(AsConfigWithChildren);
public const string Bind = nameof(Bind);
public const string BinderOptions = nameof(BinderOptions);
+ public const string BindingExtensions = nameof(BindingExtensions);
+ public const string ConfigurationChangeTokenSource = nameof(ConfigurationChangeTokenSource);
public const string Configure = nameof(Configure);
public const string CopyTo = nameof(CopyTo);
public const string ContainsKey = nameof(ContainsKey);
- public const string CoreBindingHelper = nameof(CoreBindingHelper);
public const string Count = nameof(Count);
public const string CultureInfo = nameof(CultureInfo);
public const string CultureNotFoundException = nameof(CultureNotFoundException);
public const string Enum = nameof(Enum);
public const string ErrorOnUnknownConfiguration = nameof(ErrorOnUnknownConfiguration);
- public const string GeneratedConfigurationBinder = nameof(GeneratedConfigurationBinder);
- public const string GeneratedOptionsBuilderBinder = nameof(GeneratedOptionsBuilderBinder);
- public const string GeneratedServiceCollectionBinder = nameof(GeneratedServiceCollectionBinder);
+ public const string Exception = nameof(Exception);
public const string Get = nameof(Get);
public const string GetBinderOptions = nameof(GetBinderOptions);
public const string GetChildren = nameof(GetChildren);
public const string IConfiguration = nameof(IConfiguration);
public const string IConfigurationSection = nameof(IConfigurationSection);
public const string Int32 = "int";
+ public const string InterceptsLocation = nameof(InterceptsLocation);
public const string InvalidOperationException = nameof(InvalidOperationException);
public const string InvariantCulture = nameof(InvariantCulture);
+ public const string IOptionsChangeTokenSource = nameof(IOptionsChangeTokenSource);
+ public const string IServiceCollection = nameof(IServiceCollection);
public const string Length = nameof(Length);
+ public const string NumberStyles = nameof(NumberStyles);
public const string Parse = nameof(Parse);
public const string Path = nameof(Path);
public const string Resize = nameof(Resize);
public const string TOptions = nameof(TOptions);
public const string TryCreate = nameof(TryCreate);
public const string TryGetValue = nameof(TryGetValue);
- public const string TryParse = nameof(TryParse);
+ public const string Type = nameof(Type);
public const string Uri = nameof(Uri);
public const string ValidateConfigurationKeys = nameof(ValidateConfigurationKeys);
public const string Value = nameof(Value);
}
- private bool ShouldEmitBinders() =>
+ private bool ShouldEmitBindingExtensions() =>
ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Any) ||
ShouldEmitMethods(MethodsToGen_Extensions_OptionsBuilder.Any) ||
ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection.Any);
+ private void EmitInterceptsLocationAnnotations(Enum generatedBindingOverload)
+ {
+ // The only time a generated binding method won't have any locations to
+ // intercept is when either of these methods are used as helpers for
+ // other generated OptionsBuilder or ServiceCollection binding extensions.
+ bool interceptsCalls = _sourceGenSpec.InterceptionInfo.TryGetValue(generatedBindingOverload, out List<InterceptorLocationInfo>? infoList);
+ Debug.Assert(interceptsCalls ||
+ generatedBindingOverload is MethodsToGen_Extensions_ServiceCollection.Configure_T_name_BinderOptions ||
+ generatedBindingOverload is MethodsToGen_Extensions_OptionsBuilder.Bind_T_BinderOptions);
+
+ if (interceptsCalls)
+ {
+ EmitInterceptsLocationAnnotations(infoList);
+ }
+ }
+
+ private void EmitInterceptsLocationAnnotations(List<InterceptorLocationInfo> infoList)
+ {
+ foreach (InterceptorLocationInfo info in infoList)
+ {
+ _writer.WriteLine($@"[{Identifier.InterceptsLocation}Attribute(@""{info.FilePath}"", {info.LineNumber}, {info.CharacterNumber})]");
+ }
+ }
+
+ private void EmitBindingExtStartRegion(string targetType)
+ {
+ Debug.Assert(_emittedExtsTargetType is null);
+
+ EmitBlankLineIfRequired();
+ _emittedExtsTargetType = targetType;
+ EmitBindingExtRegionText(isStart: true);
+ _emitBlankLineBeforeNextStatement = false;
+ }
+
+ private void EmitBindingExtEndRegion()
+ {
+ Debug.Assert(_emittedExtsTargetType is not null);
+
+ EmitBindingExtRegionText(isStart: false);
+ _emittedExtsTargetType = null;
+ _emitBlankLineBeforeNextStatement = true;
+ }
+
+ private void EmitBindingExtRegionText(bool isStart)
+ {
+ string endSource = isStart ? string.Empty : "end";
+ _writer.WriteLine($"#{endSource}region {_emittedExtsTargetType} extensions.");
+ }
+
/// <summary>
/// Starts a block of source code.
/// </summary>
_emitBlankLineBeforeNextStatement = true;
}
- private void EmitCheckForNullArgument_WithBlankLine_IfRequired(bool isValueType)
- {
- if (!isValueType)
- {
- EmitCheckForNullArgument_WithBlankLine(Identifier.obj);
- }
- }
-
private void EmitCheckForNullArgument_WithBlankLine(string paramName)
{
- string exceptionTypeDisplayString = _useFullyQualifiedNames
- ? "global::System.ArgumentNullException"
- : "ArgumentNullException";
-
_writer.WriteLine($$"""
if ({{paramName}} is null)
{
- throw new {{exceptionTypeDisplayString}}(nameof({{paramName}}));
+ throw new ArgumentNullException(nameof({{paramName}}));
}
""");
if (!type.CanInitialize)
{
- _writer.WriteLine(GetInitException(type.InitExceptionMessage) + ";");
+ _writer.WriteLine($@"throw new {Identifier.InvalidOperationException}(""{type.InitExceptionMessage}"");");
return true;
}
return false;
}
- private void EmitRootBindingClassStartBlock(string className)
- {
- EmitBlankLineIfRequired();
- EmitStartBlock($$"""
- /// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
- {{GetGeneratedCodeAttributeSrc()}}
- internal static class {{className}}
- """);
-
- _emitBlankLineBeforeNextStatement = false;
- }
-
- private string GetGeneratedCodeAttributeSrc()
- {
- string attributeRefExpr = _useFullyQualifiedNames ? $"global::System.CodeDom.Compiler.GeneratedCodeAttribute" : "GeneratedCode";
- return $@"[{attributeRefExpr}(""{s_assemblyName.Name}"", ""{s_assemblyName.Version}"")]";
- }
-
- private string GetInitException(string message) => $@"throw new {GetInvalidOperationDisplayName()}(""{message}"")";
-
private string GetIncrementalIdentifier(string prefix) => $"{prefix}{_valueSuffixIndex++}";
- private string GetInitalizeMethodDisplayString(ObjectSpec type) =>
- GetHelperMethodDisplayString($"{nameof(MethodsToGen_CoreBindingHelper.Initialize)}{type.DisplayStringWithoutSpecialCharacters}");
-
- private string GetTypeDisplayString(TypeSpec type) => _useFullyQualifiedNames ? type.FullyQualifiedDisplayString : type.MinimalDisplayString;
-
- private string GetHelperMethodDisplayString(string methodName)
- {
- if (_useFullyQualifiedNames)
- {
- methodName = FullyQualifiedDisplayString.CoreBindingHelper + "." + methodName;
- }
-
- return methodName;
- }
-
- private string GetInvalidOperationDisplayName() => _useFullyQualifiedNames ? FullyQualifiedDisplayString.InvalidOperationException : Identifier.InvalidOperationException;
+ private static string GetInitalizeMethodDisplayString(ObjectSpec type) =>
+ $"{nameof(MethodsToGen_CoreBindingHelper.Initialize)}{type.DisplayString.ToIdentifierSubstring()}";
}
}
+
+ internal static class EmitterExtensions
+ {
+ public static string ToIdentifierSubstring(this string typeDisplayName) =>
+ typeDisplayName
+ .Replace("[]", nameof(Array))
+ .Replace(", ", string.Empty)
+ .Replace(".", string.Empty)
+ .Replace("<", string.Empty)
+ .Replace(">", string.Empty);
+ }
}
{
private bool ShouldEmitMethods(MethodsToGen_Extensions_OptionsBuilder methods) => (_sourceGenSpec.MethodsToGen_OptionsBuilderExt & methods) != 0;
- private void EmitBinder_Extensions_OptionsBuilder()
+ private void EmitBindingExtensions_OptionsBuilder()
{
if (!ShouldEmitMethods(MethodsToGen_Extensions_OptionsBuilder.Any))
{
return;
}
- EmitRootBindingClassStartBlock(Identifier.GeneratedOptionsBuilderBinder);
-
+ EmitBindingExtStartRegion(TypeDisplayString.OptionsBuilderOfTOptions);
EmitBindMethods_Extensions_OptionsBuilder();
EmitBindConfigurationMethod();
-
- EmitEndBlock();
+ EmitBindingExtEndRegion();
}
private void EmitBindMethods_Extensions_OptionsBuilder()
}
const string documentation = @"/// <summary>Registers a configuration instance which <typeparamref name=""TOptions""/> will bind against.</summary>";
- const string paramList = $"{FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}";
+ const string paramList = $"{Identifier.IConfiguration} {Identifier.configuration}";
if (ShouldEmitMethods(MethodsToGen_Extensions_OptionsBuilder.Bind_T))
{
- EmitMethodStartBlock("Bind", paramList, documentation);
- _writer.WriteLine($"return global::{Identifier.GeneratedOptionsBuilderBinder}.Bind({Identifier.optionsBuilder}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
+ EmitMethodStartBlock(MethodsToGen_Extensions_OptionsBuilder.Bind_T, "Bind", paramList, documentation);
+ _writer.WriteLine($"return Bind({Identifier.optionsBuilder}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
EmitEndBlock();
}
EmitMethodStartBlock(
+ MethodsToGen_Extensions_OptionsBuilder.Bind_T_BinderOptions,
"Bind",
- paramList + $", {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}",
+ paramList + $", {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}",
documentation);
EmitCheckForNullArgument_WithBlankLine(Identifier.optionsBuilder);
_writer.WriteLine($$"""
- global::{{Identifier.GeneratedServiceCollectionBinder}}.{{Identifier.Configure}}<{{Identifier.TOptions}}>({{Identifier.optionsBuilder}}.{{Identifier.Services}}, {{Identifier.optionsBuilder}}.Name, {{Identifier.configuration}}, {{Identifier.configureOptions}});
+ {{Identifier.Configure}}<{{Identifier.TOptions}}>({{Identifier.optionsBuilder}}.{{Identifier.Services}}, {{Identifier.optionsBuilder}}.Name, {{Identifier.configuration}}, {{Identifier.configureOptions}});
return {{Identifier.optionsBuilder}};
""");
return;
}
- const string documentation = $@"/// <summary>Registers the dependency injection container to bind <typeparamref name=""TOptions""/> against the <see cref=""{FullyQualifiedDisplayString.IConfiguration}""/> obtained from the DI service provider.</summary>";
- string paramList = $"string {Identifier.configSectionPath}, {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions} = null";
+ const string documentation = $@"/// <summary>Registers the dependency injection container to bind <typeparamref name=""TOptions""/> against the <see cref=""{Identifier.IConfiguration}""/> obtained from the DI service provider.</summary>";
+ string paramList = $"string {Identifier.configSectionPath}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions} = null";
- EmitMethodStartBlock("BindConfiguration", paramList, documentation);
+ EmitMethodStartBlock(MethodsToGen_Extensions_OptionsBuilder.BindConfiguration, "BindConfiguration", paramList, documentation);
EmitCheckForNullArgument_WithBlankLine(Identifier.optionsBuilder);
EmitCheckForNullArgument_WithBlankLine(Identifier.configSectionPath);
- EmitStartBlock($"{Identifier.optionsBuilder}.{Identifier.Configure}<{FullyQualifiedDisplayString.IConfiguration}>(({Identifier.obj}, {Identifier.configuration}) =>");
-
+ EmitStartBlock($"{Identifier.optionsBuilder}.{Identifier.Configure}<{Identifier.IConfiguration}>(({Identifier.obj}, {Identifier.configuration}) =>");
+ EmitCheckForNullArgument_WithBlankLine(Identifier.obj);
+ EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
_writer.WriteLine($$"""
- {{FullyQualifiedDisplayString.IConfiguration}} {{Identifier.section}} = string.Equals(string.Empty, {{Identifier.configSectionPath}}, global::System.StringComparison.OrdinalIgnoreCase) ? {{Identifier.configuration}} : {{Identifier.configuration}}.{{Identifier.GetSection}}({{Identifier.configSectionPath}});
- {{FullyQualifiedDisplayString.CoreBindingHelper}}.{{nameof(MethodsToGen_CoreBindingHelper.BindCoreUntyped)}}({{Identifier.section}}, {{Identifier.obj}}, typeof({{Identifier.TOptions}}), {{Identifier.configureOptions}});
+ {{Identifier.IConfiguration}} {{Identifier.section}} = string.Equals(string.Empty, {{Identifier.configSectionPath}}, StringComparison.OrdinalIgnoreCase) ? {{Identifier.configuration}} : {{Identifier.configuration}}.{{Identifier.GetSection}}({{Identifier.configSectionPath}});
+ {{nameof(MethodsToGen_CoreBindingHelper.BindCoreMain)}}({{Identifier.section}}, {{Identifier.obj}}, typeof({{Identifier.TOptions}}), {{Identifier.configureOptions}});
""");
EmitEndBlock(endBraceTrailingSource: ");");
_writer.WriteLine();
_writer.WriteLine($$"""
- {{FullyQualifiedDisplayString.AddSingleton}}<{{FullyQualifiedDisplayString.IOptionsChangeTokenSource}}<{{Identifier.TOptions}}>, {{FullyQualifiedDisplayString.ConfigurationChangeTokenSource}}<{{Identifier.TOptions}}>>({{Identifier.optionsBuilder}}.{{Identifier.Services}});
+ {{Identifier.optionsBuilder}}.{{Identifier.Services}}.{{Identifier.AddSingleton}}<{{Identifier.IOptionsChangeTokenSource}}<{{Identifier.TOptions}}>, {{Identifier.ConfigurationChangeTokenSource}}<{{Identifier.TOptions}}>>();
return {{Identifier.optionsBuilder}};
""");
EmitEndBlock();
}
- private void EmitMethodStartBlock(string methodName, string paramList, string documentation)
+ private void EmitMethodStartBlock(MethodsToGen_Extensions_OptionsBuilder method, string methodName, string paramList, string documentation)
{
- paramList = $"this {FullyQualifiedDisplayString.OptionsBuilderOfTOptions} {Identifier.optionsBuilder}, {paramList}";
-
+ paramList = $"this {TypeDisplayString.OptionsBuilderOfTOptions} {Identifier.optionsBuilder}, {paramList}";
EmitBlankLineIfRequired();
_writer.WriteLine(documentation);
- EmitStartBlock($"public static {FullyQualifiedDisplayString.OptionsBuilderOfTOptions} {methodName}<{Identifier.TOptions}>({paramList}) where {Identifier.TOptions} : class");
+ EmitInterceptsLocationAnnotations(method);
+ EmitStartBlock($"public static {TypeDisplayString.OptionsBuilderOfTOptions} {methodName}<{Identifier.TOptions}>({paramList}) where {Identifier.TOptions} : class");
}
}
}
{
private bool ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection methods) => (_sourceGenSpec.MethodsToGen_ServiceCollectionExt & methods) != 0;
- private void EmitBinder_Extensions_IServiceCollection()
+ private void EmitBindingExtensions_IServiceCollection()
{
if (!ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection.Any))
{
return;
}
- EmitRootBindingClassStartBlock(Identifier.GeneratedServiceCollectionBinder);
+ EmitBindingExtStartRegion(Identifier.IServiceCollection);
+ EmitConfigureMethods();
+ EmitBindingExtEndRegion();
+ }
+ private void EmitConfigureMethods()
+ {
const string defaultNameExpr = "string.Empty";
- const string configureMethodString = $"global::{Identifier.GeneratedServiceCollectionBinder}.{Identifier.Configure}";
- string configParam = $"{FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}";
+ string configParam = $"{Identifier.IConfiguration} {Identifier.configuration}";
if (ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection.Configure_T))
{
- EmitStartMethod(configParam);
- _writer.WriteLine($"return {configureMethodString}<{Identifier.TOptions}>({Identifier.services}, {defaultNameExpr}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
+ EmitStartMethod(MethodsToGen_Extensions_ServiceCollection.Configure_T, configParam);
+ _writer.WriteLine($"return {Identifier.Configure}<{Identifier.TOptions}>({Identifier.services}, {defaultNameExpr}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
EmitEndBlock();
}
if (ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection.Configure_T_name))
{
EmitStartMethod(
+ MethodsToGen_Extensions_ServiceCollection.Configure_T_name,
paramList: $"string? {Identifier.name}, " + configParam);
- _writer.WriteLine($"return {configureMethodString}<{Identifier.TOptions}>({Identifier.services}, {Identifier.name}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
+ _writer.WriteLine($"return {Identifier.Configure}<{Identifier.TOptions}>({Identifier.services}, {Identifier.name}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
EmitEndBlock();
}
if (ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection.Configure_T_BinderOptions))
{
EmitStartMethod(
- paramList: configParam + $", {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}");
- _writer.WriteLine($"return {configureMethodString}<{Identifier.TOptions}>({Identifier.services}, {defaultNameExpr}, {Identifier.configuration}, {Identifier.configureOptions});");
+ MethodsToGen_Extensions_ServiceCollection.Configure_T_BinderOptions,
+ paramList: configParam + $", {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}");
+ _writer.WriteLine($"return {Identifier.Configure}<{Identifier.TOptions}>({Identifier.services}, {defaultNameExpr}, {Identifier.configuration}, {Identifier.configureOptions});");
EmitEndBlock();
}
// Core Configure method that the other overloads call.
// Like the others, it is public API that could be called directly by users.
// So, it is always generated whenever a Configure overload is called.
- string optionsNamespaceName = "global::Microsoft.Extensions.Options";
- string bindCoreUntypedDisplayString = GetHelperMethodDisplayString(nameof(MethodsToGen_CoreBindingHelper.BindCoreUntyped));
+ string optionsNamespaceName = "Microsoft.Extensions.Options";
- EmitStartMethod(paramList: $"string? {Identifier.name}, " + configParam + $", {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}");
+ EmitStartMethod(MethodsToGen_Extensions_ServiceCollection.Configure_T_name_BinderOptions, paramList: $"string? {Identifier.name}, " + configParam + $", {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}");
EmitCheckForNullArgument_WithBlankLine(Identifier.services);
EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
_writer.WriteLine($$"""
- global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptions({{Identifier.services}});
- {{FullyQualifiedDisplayString.AddSingleton}}<{{FullyQualifiedDisplayString.IOptionsChangeTokenSource}}<{{Identifier.TOptions}}>>({{Identifier.services}}, new {{FullyQualifiedDisplayString.ConfigurationChangeTokenSource}}<{{Identifier.TOptions}}>({{Identifier.name}}, {{Identifier.configuration}}));
- return {{FullyQualifiedDisplayString.AddSingleton}}<{{optionsNamespaceName}}.IConfigureOptions<{{Identifier.TOptions}}>>({{Identifier.services}}, new {{optionsNamespaceName}}.ConfigureNamedOptions<{{Identifier.TOptions}}>({{Identifier.name}}, {{Identifier.obj}} => {{bindCoreUntypedDisplayString}}({{Identifier.configuration}}, {{Identifier.obj}}, typeof({{Identifier.TOptions}}), {{Identifier.configureOptions}})));
+ OptionsServiceCollectionExtensions.AddOptions({{Identifier.services}});
+ {{Identifier.services}}.{{Identifier.AddSingleton}}<{{Identifier.IOptionsChangeTokenSource}}<{{Identifier.TOptions}}>>(new {{Identifier.ConfigurationChangeTokenSource}}<{{Identifier.TOptions}}>({{Identifier.name}}, {{Identifier.configuration}}));
+ return {{Identifier.services}}.{{Identifier.AddSingleton}}<{{optionsNamespaceName}}.IConfigureOptions<{{Identifier.TOptions}}>>(new {{optionsNamespaceName}}.ConfigureNamedOptions<{{Identifier.TOptions}}>({{Identifier.name}}, {{Identifier.obj}} => {{nameof(MethodsToGen_CoreBindingHelper.BindCoreMain)}}({{Identifier.configuration}}, {{Identifier.obj}}, typeof({{Identifier.TOptions}}){{Identifier.configureOptions}})));
""");
EmitEndBlock();
-
- EmitEndBlock();
- _emitBlankLineBeforeNextStatement = true;
}
- private void EmitStartMethod(string paramList)
+ private void EmitStartMethod(MethodsToGen_Extensions_ServiceCollection overload, string paramList)
{
- paramList = $"this {FullyQualifiedDisplayString.IServiceCollection} {Identifier.services}, {paramList}";
+ paramList = $"this {Identifier.IServiceCollection} {Identifier.services}, {paramList}";
EmitBlankLineIfRequired();
- EmitStartBlock($$"""
- /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
- public static {{FullyQualifiedDisplayString.IServiceCollection}} {{Identifier.Configure}}<{{Identifier.TOptions}}>({{paramList}}) where {{Identifier.TOptions}} : class
- """);
+ _writer.WriteLine("/// <summary>Registers a configuration instance which TOptions will bind against.</summary>");
+ EmitInterceptsLocationAnnotations(overload);
+ EmitStartBlock($"public static {Identifier.IServiceCollection} {Identifier.Configure}<{Identifier.TOptions}>({paramList}) where {Identifier.TOptions} : class");
}
}
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Operations;
+using Microsoft.CodeAnalysis.Text;
+
+namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
+{
+ internal sealed record InterceptorLocationInfo
+ {
+ public InterceptorLocationInfo(IInvocationOperation operation)
+ {
+ SyntaxNode operationSyntax = operation.Syntax;
+ TextSpan operationSpan = operationSyntax.Span;
+ SyntaxTree operationSyntaxTree = operationSyntax.SyntaxTree;
+
+ FilePath = GetInterceptorFilePath(operationSyntaxTree, operation.SemanticModel?.Compilation.Options.SourceReferenceResolver);
+
+ FileLinePositionSpan span = operationSyntaxTree.GetLineSpan(operationSpan);
+ LineNumber = span.StartLinePosition.Line + 1;
+
+ // Calculate the character offset to the end of the binding invocation detected.
+ int invocationLength = ((MemberAccessExpressionSyntax)((InvocationExpressionSyntax)operationSyntax).Expression).Expression.Span.Length;
+ CharacterNumber = span.StartLinePosition.Character + invocationLength + 2;
+ }
+
+ public string FilePath { get; }
+ public int LineNumber { get; }
+ public int CharacterNumber { get; }
+
+ // Utilize the same logic used by the interceptors API for resolving the source mapped value of a path.
+ // https://github.com/dotnet/roslyn/blob/f290437fcc75dad50a38c09e0977cce13a64f5ba/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs#L1063-L1064
+ private static string GetInterceptorFilePath(SyntaxTree tree, SourceReferenceResolver? resolver) =>
+ resolver?.NormalizePath(tree.FilePath, baseFilePath: null) ?? tree.FilePath;
+ }
+
+ internal sealed record ConfigurationBinderInterceptorInfo
+ {
+ private OverloadInterceptorInfo? _bind_Instance;
+ private OverloadInterceptorInfo? _bind_instance_BinderOptions;
+ private OverloadInterceptorInfo? _bind_key_instance;
+
+ public void RegisterOverloadInfo(MethodsToGen_ConfigurationBinder overload, TypeSpec type, IInvocationOperation operation)
+ {
+ OverloadInterceptorInfo overloadInfo = DetermineOverload(overload, initIfNull: true);
+ overloadInfo.RegisterLocationInfo(type, operation);
+ }
+
+ public OverloadInterceptorInfo GetOverloadInfo(MethodsToGen_ConfigurationBinder overload) =>
+ DetermineOverload(overload, initIfNull: false) ?? throw new ArgumentNullException(nameof(overload));
+
+ private OverloadInterceptorInfo? DetermineOverload(MethodsToGen_ConfigurationBinder overload, bool initIfNull)
+ {
+ return overload switch
+ {
+ MethodsToGen_ConfigurationBinder.Bind_instance => InitIfNull(ref _bind_Instance),
+ MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions => InitIfNull(ref _bind_instance_BinderOptions),
+ MethodsToGen_ConfigurationBinder.Bind_key_instance => InitIfNull(ref _bind_key_instance),
+ _ => throw new InvalidOperationException(nameof(overload)),
+ };
+
+ OverloadInterceptorInfo InitIfNull(ref OverloadInterceptorInfo? info)
+ {
+ if (initIfNull)
+ {
+ info ??= new OverloadInterceptorInfo();
+ }
+
+ return info;
+ }
+ }
+ }
+
+ internal sealed record OverloadInterceptorInfo : IEnumerable<KeyValuePair<TypeSpec, List<InterceptorLocationInfo>>>
+ {
+ private readonly Dictionary<TypeSpec, List<InterceptorLocationInfo>> _typeInterceptionInfo = new();
+
+ public void RegisterLocationInfo(TypeSpec type, IInvocationOperation operation) =>
+ _typeInterceptionInfo.RegisterCacheEntry(type, new InterceptorLocationInfo(operation));
+
+ public IEnumerator<KeyValuePair<TypeSpec, List<InterceptorLocationInfo>>> GetEnumerator() => _typeInterceptionInfo.GetEnumerator();
+
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ }
+}
{
None = 0x0,
BindCore = 0x1,
- BindCoreUntyped = 0x2,
- GetCore = 0x4,
- GetValueCore = 0x8,
+ GetCore = 0x2,
+ GetValueCore = 0x4,
+ BindCoreMain = 0x8,
Initialize = 0x10,
- AsConfigWithChildren = 0x20,
+ HasValueOrChildren = 0x20,
+ AsConfigWithChildren = 0x40,
}
/// <summary>
IsValidMethodName_OptionsConfigurationServiceCollectionExtensions(name);
}
- private static bool IsBindingOperation(IInvocationOperation operation)
+ public static bool IsBindingOperation(IInvocationOperation operation)
{
if (operation.TargetMethod is not IMethodSymbol
{
if (GetTargetTypeForRootInvocationCore(type, invocation.Location) is TypeSpec typeSpec)
{
- Dictionary<MethodsToGen_ConfigurationBinder, HashSet<TypeSpec>> types = _sourceGenSpec.TypesForGen_ConfigurationBinder_BindMethods;
-
- if (!types.TryGetValue(overload, out HashSet<TypeSpec>? typeSpecs))
- {
- types[overload] = typeSpecs = new HashSet<TypeSpec>();
- }
-
- _sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
- typeSpecs.Add(typeSpec);
+ RegisterAsInterceptor_ConfigBinder_BindMethod(overload, typeSpec, invocation.Operation);
}
static ITypeSymbol? ResolveType(IOperation conversionOperation) =>
if (GetTargetTypeForRootInvocation(type, invocation.Location) is TypeSpec typeSpec)
{
- _sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.GetCore, typeSpec);
+ RegisterAsInterceptor_ConfigBinder(overload, invocation.Operation);
+ RegisterTypeForGetCoreGen(typeSpec);
}
}
if (IsParsableFromString(effectiveType, out _) &&
GetTargetTypeForRootInvocationCore(type, invocation.Location) is TypeSpec typeSpec)
{
- _sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
+ RegisterAsInterceptor_ConfigBinder(overload, invocation.Operation);
RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.GetValueCore, typeSpec);
}
}
+
+ private void RegisterAsInterceptor_ConfigBinder(MethodsToGen_ConfigurationBinder overload, IInvocationOperation operation)
+ {
+ _sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
+ RegisterAsInterceptor(overload, operation);
+ }
+
+ /// <summary>
+ /// Registers generated Bind methods as interceptors. This is done differently from other root
+ /// methods <see cref="RegisterAsInterceptor(Enum, IInvocationOperation)"/> because we need to
+ /// explicitly account for the type to bind, to avoid type-check issues for polymorphic objects.
+ /// </summary>
+ private void RegisterAsInterceptor_ConfigBinder_BindMethod(MethodsToGen_ConfigurationBinder overload, TypeSpec typeSpec, IInvocationOperation operation)
+ {
+ _sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
+ _sourceGenSpec.InterceptionInfo_ConfigBinder.RegisterOverloadInfo(overload, typeSpec, operation);
+ }
}
}
}
return;
}
- // We are going to emit calls to APIs on IServiceCollection.
- _sourceGenSpec.TypeNamespaces.Add("Microsoft.Extensions.DependencyInjection");
-
if (targetMethod.Name is "Bind")
{
RegisterBindInvocation(invocation, typeSpec);
return;
}
- if (paramCount is 2)
- {
- _sourceGenSpec.MethodsToGen_OptionsBuilderExt |= MethodsToGen_Extensions_OptionsBuilder.Bind_T;
- }
- else if (paramCount is 3 && SymbolEqualityComparer.Default.Equals(_typeSymbols.ActionOfBinderOptions, @params[2].Type))
+ MethodsToGen_Extensions_OptionsBuilder overload = paramCount switch
{
- _sourceGenSpec.MethodsToGen_OptionsBuilderExt |= MethodsToGen_Extensions_OptionsBuilder.Bind_T_BinderOptions;
- }
- else
+ 2 => MethodsToGen_Extensions_OptionsBuilder.Bind_T,
+ 3 when SymbolEqualityComparer.Default.Equals(_typeSymbols.ActionOfBinderOptions, @params[2].Type) =>
+ MethodsToGen_Extensions_OptionsBuilder.Bind_T_BinderOptions,
+ _ => MethodsToGen_Extensions_OptionsBuilder.None
+ };
+
+ if (overload is not MethodsToGen_Extensions_OptionsBuilder.None)
{
- return;
+ RegisterAsInterceptor_OptionsBuilder(overload, operation);
+ RegisterTypeForMethodGen(MethodsToGen_Extensions_ServiceCollection.Configure_T_name_BinderOptions, typeSpec);
}
-
- RegisterTypeForMethodGen(MethodsToGen_Extensions_ServiceCollection.Configure_T_name_BinderOptions, typeSpec);
}
private void ParseBindConfigurationInvocation(BinderInvocation invocation, TypeSpec typeSpec)
int paramCount = @params.Length;
Debug.Assert(paramCount >= 2);
- if (paramCount is 3 && @params[1].Type.SpecialType is SpecialType.System_String && SymbolEqualityComparer.Default.Equals(_typeSymbols.ActionOfBinderOptions, @params[2].Type))
+ if (paramCount is 3 &&
+ @params[1].Type.SpecialType is SpecialType.System_String &&
+ SymbolEqualityComparer.Default.Equals(_typeSymbols.ActionOfBinderOptions, @params[2].Type))
{
- _sourceGenSpec.MethodsToGen_OptionsBuilderExt |= MethodsToGen_Extensions_OptionsBuilder.BindConfiguration_T_path_BinderOptions;
- RegisterTypeForBindCoreUntypedGen(typeSpec);
+ RegisterAsInterceptor_OptionsBuilder(MethodsToGen_Extensions_OptionsBuilder.BindConfiguration_T_path_BinderOptions, invocation.Operation);
+ RegisterTypeForBindCoreMainGen(typeSpec);
}
}
+
+ private void RegisterAsInterceptor_OptionsBuilder(MethodsToGen_Extensions_OptionsBuilder overload, IInvocationOperation operation)
+ {
+ _sourceGenSpec.MethodsToGen_OptionsBuilderExt |= overload;
+ RegisterAsInterceptor(overload, operation);
+
+ // Emitting refs to IOptionsChangeTokenSource, ConfigurationChangeTokenSource.
+ _sourceGenSpec.Namespaces.Add("Microsoft.Extensions.Options");
+
+ // Emitting refs to OptionsBuilder<T>.
+ _sourceGenSpec.Namespaces.Add("Microsoft.Extensions.DependencyInjection");
+ }
}
}
}
}
RegisterTypeForMethodGen(overload, typeSpec);
+ RegisterAsInterceptor(overload, operation);
}
private void RegisterTypeForMethodGen(MethodsToGen_Extensions_ServiceCollection overload, TypeSpec typeSpec)
{
_sourceGenSpec.MethodsToGen_ServiceCollectionExt |= overload;
- RegisterTypeForBindCoreUntypedGen(typeSpec);
+ _sourceGenSpec.Namespaces.Add("Microsoft.Extensions.DependencyInjection");
+ RegisterTypeForBindCoreMainGen(typeSpec);
}
}
}
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(MicrosoftCodeAnalysisVersion_LatestVS)" PrivateAssets="all" />
+ <!-- if MicrosoftCodeAnalysisVersion_LatestVS is still at 4.5.0 (eg: not source build) then update to a newer version. Remove this when we are able to update the value of MicrosoftCodeAnalysisVersion_LatestVS -->
+ <PackageReference Update="Microsoft.CodeAnalysis.CSharp.Workspaces" Condition="'$(MicrosoftCodeAnalysisVersion_LatestVS)' == '4.5.0'" Version="4.7.0-3.23314.3" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConfigurationBindingGenerator.cs" />
<Compile Include="ConfigurationBindingGenerator.Emitter.cs" />
<Compile Include="ConfigurationBindingGenerator.Parser.cs" />
+ <Compile Include="ConfigurationBindingGenerator.Suppressor.cs" />
<Compile Include="Helpers\Emitter\ConfigurationBinder.cs" />
- <Compile Include="Helpers\Emitter\CoreBindingHelper.cs" />
+ <Compile Include="Helpers\Emitter\CoreBindingHelpers.cs" />
<Compile Include="Helpers\Emitter\ExceptionMessages.cs" />
<Compile Include="Helpers\Emitter\Helpers.cs" />
<Compile Include="Helpers\Emitter\OptionsBuilderConfigurationExtensions.cs" />
<Compile Include="Helpers\Emitter\OptionsConfigurationServiceCollectionExtensions.cs" />
+ <Compile Include="Helpers\InterceptorLocationInfo.cs" />
<Compile Include="Helpers\MethodsToGen.cs" />
<Compile Include="Helpers\Parser\BinderInvocation.cs" />
<Compile Include="Helpers\Parser\ConfigurationBinder.cs" />
public List<ParameterSpec> ConstructorParameters { get; } = new();
- private string _displayStringWithoutSpecialCharacters;
- public string DisplayStringWithoutSpecialCharacters =>
- _displayStringWithoutSpecialCharacters ??= $"{MinimalDisplayString.Replace(".", string.Empty).Replace("<", string.Empty).Replace(">", string.Empty)}";
-
public override bool NeedsMemberBinding => CanInitialize &&
Properties.Values.Count > 0 &&
Properties.Values.Any(p => p.ShouldBind());
_parseMethodName ??= StringParsableTypeKind is StringParsableTypeKind.ByteArray
? "ParseByteArray"
// MinimalDisplayString.Length is certainly > 2.
- : $"Parse{(char.ToUpper(MinimalDisplayString[0]) + MinimalDisplayString.Substring(1)).Replace(".", "")}";
+ : $"Parse{(char.ToUpper(DisplayString[0]) + DisplayString.Substring(1)).Replace(".", "")}";
return _parseMethodName;
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
using System.Collections.Generic;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
internal sealed record SourceGenerationSpec
{
+ public Dictionary<Enum, List<InterceptorLocationInfo>> InterceptionInfo { get; } = new();
+ public ConfigurationBinderInterceptorInfo InterceptionInfo_ConfigBinder { get; } = new();
+
public Dictionary<MethodsToGen_CoreBindingHelper, HashSet<TypeSpec>> TypesForGen_CoreBindingHelper_Methods { get; } = new();
- public Dictionary<MethodsToGen_ConfigurationBinder, HashSet<TypeSpec>> TypesForGen_ConfigurationBinder_BindMethods { get; } = new();
public HashSet<ParsableFromStringSpec> PrimitivesForHelperGen { get; } = new();
- public HashSet<string> TypeNamespaces { get; } = new()
+ public HashSet<string> Namespaces { get; } = new()
{
"System",
"System.CodeDom.Compiler",
"System.Globalization",
+ "System.Runtime.CompilerServices",
"Microsoft.Extensions.Configuration",
};
{
IsValueType = type.IsValueType;
Namespace = type.ContainingNamespace?.ToDisplayString();
- FullyQualifiedDisplayString = type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
- MinimalDisplayString = type.ToDisplayString(s_minimalDisplayFormat);
- Name = Namespace + "." + MinimalDisplayString.Replace(".", "+");
+ DisplayString = type.ToDisplayString(s_minimalDisplayFormat);
+ Name = Namespace + "." + DisplayString.Replace(".", "+");
IsInterface = type.TypeKind is TypeKind.Interface;
}
public string Name { get; }
- public string FullyQualifiedDisplayString { get; }
-
- public string MinimalDisplayString { get; }
+ public string DisplayString { get; }
public string? Namespace { get; }
<value>The collection element type is not supported: '{0}'.</value>
</data>
<data name="Language VersionIsNotSupportedMessageFormat" xml:space="preserve">
- <value>The project's language version has to be at least 'C# 11'.</value>
+ <value>The project's language version has to be at least 'C# 12'.</value>
</data>
<data name="LanguageVersionIsNotSupportedTitle" xml:space="preserve">
- <value>Language version is required to be at least C# 11</value>
+ <value>Language version is required to be at least C# 12</value>
</data>
<data name="MissingPublicInstanceConstructor" xml:space="preserve">
<value>Cannot create instance of type '{0}' because it is missing a public instance constructor.</value>
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">Jazyková verze projektu musí být alespoň C# 11</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">Jazyková verze projektu musí být alespoň C# 11</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">Verze jazyka musí být alespoň C# 11</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">Verze jazyka musí být alespoň C# 11</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">Die Sprachversion des Projekts muss mindestens „C# 11“ sein</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">Die Sprachversion des Projekts muss mindestens „C# 11“ sein</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">Die Sprachversion muss mindestens C# 11 sein</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">Die Sprachversion muss mindestens C# 11 sein</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">La versión del lenguaje del proyecto debe ser al menos "C# 11".</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">La versión del lenguaje del proyecto debe ser al menos "C# 11".</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">La versión del lenguaje debe ser al menos C# 11</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">La versión del lenguaje debe ser al menos C# 11</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">La version de langage du projet doit être au moins « C# 11 ».</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">La version de langage du projet doit être au moins « C# 11 ».</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">La version du langage doit être au moins C# 11</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">La version du langage doit être au moins C# 11</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">La versione del linguaggio del progetto deve essere almeno 'C# 11'.</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">La versione del linguaggio del progetto deve essere almeno 'C# 11'.</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">La versione del linguaggio deve essere almeno C# 11</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">La versione del linguaggio deve essere almeno C# 11</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">プロジェクトの言語バージョンは少なくとも 'C# 11' である必要があります。</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">プロジェクトの言語バージョンは少なくとも 'C# 11' である必要があります。</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">言語バージョンは少なくとも C# 11 である必要があります</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">言語バージョンは少なくとも C# 11 である必要があります</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">프로젝트의 언어 버전은 'C# 11' 이상이어야 합니다.</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">프로젝트의 언어 버전은 'C# 11' 이상이어야 합니다.</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">언어 버전은 C# 11 이상이어야 합니다.</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">언어 버전은 C# 11 이상이어야 합니다.</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">Wersja językowa projektu musi mieć wartość co najmniej „C# 11”.</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">Wersja językowa projektu musi mieć wartość co najmniej „C# 11”.</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">Wymagana jest wersja językowa co najmniej C# 11</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">Wymagana jest wersja językowa co najmniej C# 11</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">A versão do idioma do projeto deve ser no mínimo 'C# 11'.</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">A versão do idioma do projeto deve ser no mínimo 'C# 11'.</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">A versão do idioma deve ser pelo menos C# 11</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">A versão do idioma deve ser pelo menos C# 11</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">Версия языка проекта должна быть не ниже "C# 11".</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">Версия языка проекта должна быть не ниже "C# 11".</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">Версия языка должна быть не ниже C# 11</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">Версия языка должна быть не ниже C# 11</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">Projenin dil sürümü en az 'C# 11' olmalıdır.</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">Projenin dil sürümü en az 'C# 11' olmalıdır.</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">Dil sürümünün en az C# 11 olması gerekir</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">Dil sürümünün en az C# 11 olması gerekir</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">项目的语言版本必须至少为 "C# 11"。</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">项目的语言版本必须至少为 "C# 11"。</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">语言版本必须至少为 C# 11</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">语言版本必须至少为 C# 11</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
<note />
</trans-unit>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
- <source>The project's language version has to be at least 'C# 11'.</source>
- <target state="translated">專案的語言版本必須至少為 'C# 11'。</target>
+ <source>The project's language version has to be at least 'C# 12'.</source>
+ <target state="needs-review-translation">專案的語言版本必須至少為 'C# 11'。</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
- <source>Language version is required to be at least C# 11</source>
- <target state="translated">語言版本要求至少為 C#11</target>
+ <source>Language version is required to be at least C# 12</source>
+ <target state="needs-review-translation">語言版本要求至少為 C#11</target>
<note />
</trans-unit>
<trans-unit id="MissingPublicInstanceConstructor">
using System.Globalization;
using System.Linq;
using System.Reflection;
-using System.Text;
#if BUILDING_SOURCE_GENERATOR_TESTS
using Microsoft.Extensions.Configuration;
#endif
ValidateGeolocation(obj);
}
+#if !BUILDING_SOURCE_GENERATOR_TESTS
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
public void TraceSwitchTest()
{
Assert.Equal("Info", ts.Value);
#endif // NETCOREAPP
}
+#endif
private void ValidateGeolocation(IGeolocation location)
{
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
- public static T? Get<T>(this global::Microsoft.Extensions.Configuration.IConfiguration configuration) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.Collections.Generic;
using System.Globalization;
using System.Linq;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 17)]
+ public static T? Get<T>(this IConfiguration configuration) => (T?)(GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClassWithCustomCollections = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "CustomDictionary", "CustomList", "IReadOnlyList", "IReadOnlyDictionary" });
public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref Program.CustomDictionary<string, int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.CustomList obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref ICollection<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref IReadOnlyList<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
if (obj is not ICollection<int> temp)
{
return;
public static void BindCore(IConfiguration configuration, ref Dictionary<string, int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref IDictionary<string, int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref IReadOnlyDictionary<string, int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
if (obj is not IDictionary<string, int> temp)
{
return;
public static void BindCore(IConfiguration configuration, ref Program.MyClassWithCustomCollections obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClassWithCustomCollections), s_configKeys_ProgramMyClassWithCustomCollections, configuration, binderOptions);
if (AsConfigWithChildren(configuration.GetSection("CustomDictionary")) is IConfigurationSection section1)
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, binderOptions: null);
-
- /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetBinderOptions(configureOptions));
+ using System;
+ using System.CodeDom.Compiler;
- /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration.GetSection(key), ref obj, binderOptions: null);
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
- private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 13, 18)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, object? obj)
+ {
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
- public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration, ref typedObj, binderOptions: null);
+ }
+
+ /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 14, 24)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, object? obj, Action<BinderOptions>? configureOptions)
+ {
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration, ref typedObj, GetBinderOptions(configureOptions));
+ }
+
+ /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 15, 24)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, string key, object? obj)
{
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration.GetSection(key), ref typedObj, binderOptions: null);
+ }
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
+ private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
+
+ public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
+ {
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Dictionary<string, Program.MyClass2> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, binderOptions: null);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
- private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
-
- public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 20)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, object? obj)
{
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration, ref typedObj, binderOptions: null);
+ }
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
+ private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
+
+ public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
+ {
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Dictionary<string, Program.MyClass2> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetBinderOptions(configureOptions));
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
- private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
-
- public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 20)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, object? obj, Action<BinderOptions>? configureOptions)
{
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration, ref typedObj, GetBinderOptions(configureOptions));
+ }
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
+ private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
+
+ public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
+ {
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Dictionary<string, Program.MyClass2> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration.GetSection(key), ref obj, binderOptions: null);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
- private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
-
- public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 20)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, string key, object? obj)
{
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration.GetSection(key), ref typedObj, binderOptions: null);
+ }
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
+ private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
+
+ public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
+ {
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Dictionary<string, Program.MyClass2> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
- public static T? Get<T>(this global::Microsoft.Extensions.Configuration.IConfiguration configuration) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
-
- /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
- public static T? Get<T>(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, typeof(T), configureOptions) ?? default(T));
-
- /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
- public static object? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, type, configureOptions: null);
+ using System;
+ using System.CodeDom.Compiler;
- /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
- public static object? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, type, configureOptions);
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 38)]
+ public static T? Get<T>(this IConfiguration configuration) => (T?)(GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
+
+ /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 14, 36)]
+ public static T? Get<T>(this IConfiguration configuration, Action<BinderOptions>? configureOptions) => (T?)(GetCore(configuration, typeof(T), configureOptions) ?? default(T));
+
+ /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 13, 36)]
+ public static object? Get(this IConfiguration configuration, Type type) => GetCore(configuration, type, configureOptions: null);
+
+ /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 15, 36)]
+ public static object? Get(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions) => GetCore(configuration, type, configureOptions);
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass2 = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
BindCore(configuration, ref obj, binderOptions);
return obj;
}
-
- if (type == typeof(Program.MyClass2))
+ else if (type == typeof(Program.MyClass2))
{
var obj = new Program.MyClass2();
BindCore(configuration, ref obj, binderOptions);
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref int[] obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
var temp2 = new List<int>();
BindCore(configuration, ref temp2, binderOptions);
int originalCount = obj.Length;
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
if (configuration["MyInt"] is string value15)
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
- public static T? GetValue<T>(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, typeof(T), key) ?? default(T));
-
- /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
- public static T? GetValue<T>(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, T defaultValue) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, typeof(T), key) ?? defaultValue);
-
- /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
- public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, type, key);
+ using System;
+ using System.CodeDom.Compiler;
- /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
- public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key, object? defaultValue) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, type, key) ?? defaultValue;
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System;
using System.CodeDom.Compiler;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 13, 18)]
+ public static T? GetValue<T>(this IConfiguration configuration, string key) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? default(T));
+
+ /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 16, 24)]
+ public static T? GetValue<T>(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue);
+
+ /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 14, 24)]
+ public static object? GetValue(this IConfiguration configuration, Type type, string key) => BindingExtensions.GetValueCore(configuration, type, key);
+
+ /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 17, 24)]
+ public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue;
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
if (configuration is null)
{
return ParseInt(value, () => section.Path);
}
-
- if (type == typeof(bool?))
+ else if (type == typeof(bool?))
{
return ParseBool(value, () => section.Path);
}
-
- if (type == typeof(byte[]))
+ else if (type == typeof(byte[]))
{
return ParseByteArray(value, () => section.Path);
}
-
- if (type == typeof(CultureInfo))
+ else if (type == typeof(CultureInfo))
{
return ParseCultureInfo(value, () => section.Path);
}
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(CultureInfo)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
- public static T? GetValue<T>(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, typeof(T), key) ?? default(T));
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System;
using System.CodeDom.Compiler;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 10, 20)]
+ public static T? GetValue<T>(this IConfiguration configuration, string key) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? default(T));
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
if (configuration is null)
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
- public static T? GetValue<T>(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, T defaultValue) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, typeof(T), key) ?? defaultValue);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System;
using System.CodeDom.Compiler;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 20)]
+ public static T? GetValue<T>(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue);
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
if (configuration is null)
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
- public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, type, key);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System;
using System.CodeDom.Compiler;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 10, 20)]
+ public static object? GetValue(this IConfiguration configuration, Type type, string key) => BindingExtensions.GetValueCore(configuration, type, key);
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
if (configuration is null)
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
- public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key, object? defaultValue) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, type, key) ?? defaultValue;
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System;
using System.CodeDom.Compiler;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 11, 20)]
+ public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue;
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
if (configuration is null)
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(CultureInfo)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
- public static T? Get<T>(this global::Microsoft.Extensions.Configuration.IConfiguration configuration) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 11, 40)]
+ public static T? Get<T>(this IConfiguration configuration) => (T?)(GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref int[] obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
var temp1 = new List<int>();
BindCore(configuration, ref temp1, binderOptions);
int originalCount = obj.Length;
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
- public static T? Get<T>(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, typeof(T), configureOptions) ?? default(T));
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 11, 40)]
+ public static T? Get<T>(this IConfiguration configuration, Action<BinderOptions>? configureOptions) => (T?)(GetCore(configuration, typeof(T), configureOptions) ?? default(T));
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref int[] obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
var temp1 = new List<int>();
BindCore(configuration, ref temp1, binderOptions);
int originalCount = obj.Length;
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
- public static object? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, type, configureOptions: null);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 11, 40)]
+ public static object? Get(this IConfiguration configuration, Type type) => GetCore(configuration, type, configureOptions: null);
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass2 = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
if (configuration["MyInt"] is string 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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
- public static object? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, type, configureOptions);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 11, 20)]
+ public static object? Get(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions) => GetCore(configuration, type, configureOptions);
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass2 = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
if (configuration["MyInt"] is string 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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedOptionsBuilderBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Registers the dependency injection container to bind <typeparamref name="TOptions"/> against the <see cref="global::Microsoft.Extensions.Configuration.IConfiguration"/> obtained from the DI service provider.</summary>
- public static global::Microsoft.Extensions.Options.OptionsBuilder<TOptions> BindConfiguration<TOptions>(this global::Microsoft.Extensions.Options.OptionsBuilder<TOptions> optionsBuilder, string configSectionPath, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions = null) where TOptions : class
- {
- if (optionsBuilder is null)
- {
- throw new global::System.ArgumentNullException(nameof(optionsBuilder));
- }
+ using System;
+ using System.CodeDom.Compiler;
- if (configSectionPath is null)
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
{
- throw new global::System.ArgumentNullException(nameof(configSectionPath));
}
-
- optionsBuilder.Configure<global::Microsoft.Extensions.Configuration.IConfiguration>((obj, configuration) =>
- {
- global::Microsoft.Extensions.Configuration.IConfiguration section = string.Equals(string.Empty, configSectionPath, global::System.StringComparison.OrdinalIgnoreCase) ? configuration : configuration.GetSection(configSectionPath);
- global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCoreUntyped(section, obj, typeof(TOptions), configureOptions);
- });
-
- global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IOptionsChangeTokenSource<TOptions>, global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource<TOptions>>(optionsBuilder.Services);
- return optionsBuilder;
}
}
{
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;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ 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>
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 24)]
+ public static OptionsBuilder<TOptions> BindConfiguration<TOptions>(this OptionsBuilder<TOptions> optionsBuilder, string configSectionPath, Action<BinderOptions>? configureOptions = 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>((obj, configuration) =>
+ {
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ IConfiguration section = string.Equals(string.Empty, configSectionPath, StringComparison.OrdinalIgnoreCase) ? configuration : configuration.GetSection(configSectionPath);
+ BindCoreMain(section, obj, typeof(TOptions), configureOptions);
+ });
+
+ 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_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" });
- public static void BindCoreUntyped(this IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
+ public static void BindCoreMain(IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
- BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
if (!HasValueOrChildren(configuration))
{
return;
}
+ BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+
if (type == typeof(Program.MyClass))
{
var temp = (Program.MyClass)obj;
return;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedOptionsBuilderBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Registers a configuration instance which <typeparamref name="TOptions"/> will bind against.</summary>
- public static global::Microsoft.Extensions.Options.OptionsBuilder<TOptions> Bind<TOptions>(this global::Microsoft.Extensions.Options.OptionsBuilder<TOptions> optionsBuilder, global::Microsoft.Extensions.Configuration.IConfiguration configuration) where TOptions : class
- {
- return global::GeneratedOptionsBuilderBinder.Bind(optionsBuilder, configuration, configureOptions: null);
- }
-
- /// <summary>Registers a configuration instance which <typeparamref name="TOptions"/> will bind against.</summary>
- public static global::Microsoft.Extensions.Options.OptionsBuilder<TOptions> Bind<TOptions>(this global::Microsoft.Extensions.Options.OptionsBuilder<TOptions> optionsBuilder, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) where TOptions : class
- {
- if (optionsBuilder is null)
- {
- throw new global::System.ArgumentNullException(nameof(optionsBuilder));
- }
-
- global::GeneratedServiceCollectionBinder.Configure<TOptions>(optionsBuilder.Services, optionsBuilder.Name, configuration, configureOptions);
- return optionsBuilder;
- }
-}
+ using System;
+ using System.CodeDom.Compiler;
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedServiceCollectionBinder
-{
- /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<TOptions>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, string? name, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) where TOptions : class
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
{
- if (services is null)
- {
- throw new global::System.ArgumentNullException(nameof(services));
- }
-
- if (configuration is null)
+ public InterceptsLocationAttribute(string filePath, int line, int column)
{
- throw new global::System.ArgumentNullException(nameof(configuration));
}
-
- global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptions(services);
- global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IOptionsChangeTokenSource<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource<TOptions>(name, configuration));
- return global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCoreUntyped(configuration, obj, typeof(TOptions), configureOptions)));
}
}
{
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;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region OptionsBuilder<TOptions> extensions.
+ /// <summary>Registers a configuration instance which <typeparamref name="TOptions"/> will bind against.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 15, 24)]
+ public static OptionsBuilder<TOptions> Bind<TOptions>(this OptionsBuilder<TOptions> optionsBuilder, IConfiguration configuration) where TOptions : class
+ {
+ return Bind(optionsBuilder, configuration, configureOptions: null);
+ }
+
+ /// <summary>Registers a configuration instance which <typeparamref name="TOptions"/> will bind against.</summary>
+ public static OptionsBuilder<TOptions> Bind<TOptions>(this OptionsBuilder<TOptions> optionsBuilder, IConfiguration configuration, Action<BinderOptions>? configureOptions) where TOptions : class
+ {
+ if (optionsBuilder is null)
+ {
+ throw new ArgumentNullException(nameof(optionsBuilder));
+ }
+
+ Configure<TOptions>(optionsBuilder.Services, optionsBuilder.Name, configuration, configureOptions);
+ return optionsBuilder;
+ }
+ #endregion OptionsBuilder<TOptions> extensions.
+
+ #region IServiceCollection extensions.
+ /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
+ public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string? name, IConfiguration configuration, Action<BinderOptions>? configureOptions) where TOptions : class
+ {
+ if (services is null)
+ {
+ throw new ArgumentNullException(nameof(services));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ OptionsServiceCollectionExtensions.AddOptions(services);
+ services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, configuration));
+ return services.AddSingleton<Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(new Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => BindCoreMain(configuration, obj, typeof(TOptions)configureOptions)));
+ }
+ #endregion IServiceCollection extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" });
- public static void BindCoreUntyped(this IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
+ public static void BindCoreMain(IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
- BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
if (!HasValueOrChildren(configuration))
{
return;
}
+ BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+
if (type == typeof(Program.MyClass))
{
var temp = (Program.MyClass)obj;
return;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedOptionsBuilderBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Registers a configuration instance which <typeparamref name="TOptions"/> will bind against.</summary>
- public static global::Microsoft.Extensions.Options.OptionsBuilder<TOptions> Bind<TOptions>(this global::Microsoft.Extensions.Options.OptionsBuilder<TOptions> optionsBuilder, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) where TOptions : class
- {
- if (optionsBuilder is null)
- {
- throw new global::System.ArgumentNullException(nameof(optionsBuilder));
- }
-
- global::GeneratedServiceCollectionBinder.Configure<TOptions>(optionsBuilder.Services, optionsBuilder.Name, configuration, configureOptions);
- return optionsBuilder;
- }
-}
+ using System;
+ using System.CodeDom.Compiler;
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedServiceCollectionBinder
-{
- /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<TOptions>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, string? name, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) where TOptions : class
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
{
- if (services is null)
- {
- throw new global::System.ArgumentNullException(nameof(services));
- }
-
- if (configuration is null)
+ public InterceptsLocationAttribute(string filePath, int line, int column)
{
- throw new global::System.ArgumentNullException(nameof(configuration));
}
-
- global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptions(services);
- global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IOptionsChangeTokenSource<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource<TOptions>(name, configuration));
- return global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCoreUntyped(configuration, obj, typeof(TOptions), configureOptions)));
}
}
{
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;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region OptionsBuilder<TOptions> extensions.
+ /// <summary>Registers a configuration instance which <typeparamref name="TOptions"/> will bind against.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 15, 24)]
+ public static OptionsBuilder<TOptions> Bind<TOptions>(this OptionsBuilder<TOptions> optionsBuilder, IConfiguration configuration, Action<BinderOptions>? configureOptions) where TOptions : class
+ {
+ if (optionsBuilder is null)
+ {
+ throw new ArgumentNullException(nameof(optionsBuilder));
+ }
+
+ Configure<TOptions>(optionsBuilder.Services, optionsBuilder.Name, configuration, configureOptions);
+ return optionsBuilder;
+ }
+ #endregion OptionsBuilder<TOptions> extensions.
+
+ #region IServiceCollection extensions.
+ /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
+ public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string? name, IConfiguration configuration, Action<BinderOptions>? configureOptions) where TOptions : class
+ {
+ if (services is null)
+ {
+ throw new ArgumentNullException(nameof(services));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ OptionsServiceCollectionExtensions.AddOptions(services);
+ services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, configuration));
+ return services.AddSingleton<Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(new Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => BindCoreMain(configuration, obj, typeof(TOptions)configureOptions)));
+ }
+ #endregion IServiceCollection extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" });
- public static void BindCoreUntyped(this IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
+ public static void BindCoreMain(IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
- BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
if (!HasValueOrChildren(configuration))
{
return;
}
+ BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+
if (type == typeof(Program.MyClass))
{
var temp = (Program.MyClass)obj;
return;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, binderOptions: null);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [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 System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
- private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Prop0", "Prop1", "Prop2", "Prop3", "Prop4", "Prop5", "Prop6", "Prop8", "Prop9", "Prop10", "Prop13", "Prop14", "Prop15", "Prop16", "Prop17", "Prop19", "Prop20", "Prop21", "Prop23", "Prop24", "Prop25", "Prop26", "Prop27", "Prop7", "Prop11", "Prop12", "Prop18", "Prop22" });
-
- public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
+ #region IConfiguration extensions.
+ /// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 13, 16)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, object? obj)
{
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration, ref typedObj, binderOptions: null);
+ }
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
+ private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Prop0", "Prop1", "Prop2", "Prop3", "Prop4", "Prop5", "Prop6", "Prop8", "Prop9", "Prop10", "Prop13", "Prop14", "Prop15", "Prop16", "Prop17", "Prop19", "Prop20", "Prop21", "Prop23", "Prop24", "Prop25", "Prop26", "Prop27", "Prop7", "Prop11", "Prop12", "Prop18", "Prop22" });
+
+ public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
+ {
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
if (configuration["Prop0"] is string value0)
}
}
+
/// <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)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(byte[])}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedServiceCollectionBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<TOptions>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::Microsoft.Extensions.Configuration.IConfiguration configuration) where TOptions : class
- {
- return global::GeneratedServiceCollectionBinder.Configure<TOptions>(services, string.Empty, configuration, configureOptions: null);
- }
+ using System;
+ using System.CodeDom.Compiler;
- /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<TOptions>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, string? name, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) where TOptions : class
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
{
- if (services is null)
- {
- throw new global::System.ArgumentNullException(nameof(services));
- }
-
- if (configuration is null)
+ public InterceptsLocationAttribute(string filePath, int line, int column)
{
- throw new global::System.ArgumentNullException(nameof(configuration));
}
-
- global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptions(services);
- global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IOptionsChangeTokenSource<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource<TOptions>(name, configuration));
- return global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCoreUntyped(configuration, obj, typeof(TOptions), configureOptions)));
}
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using Microsoft.Extensions.Configuration;
+ using Microsoft.Extensions.DependencyInjection;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IServiceCollection extensions.
+ /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 14, 18)]
+ public static IServiceCollection Configure<TOptions>(this IServiceCollection services, IConfiguration configuration) where TOptions : class
+ {
+ return Configure<TOptions>(services, string.Empty, configuration, configureOptions: null);
+ }
+
+ /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
+ public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string? name, IConfiguration configuration, Action<BinderOptions>? configureOptions) where TOptions : class
+ {
+ if (services is null)
+ {
+ throw new ArgumentNullException(nameof(services));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ OptionsServiceCollectionExtensions.AddOptions(services);
+ services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, configuration));
+ return services.AddSingleton<Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(new Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => BindCoreMain(configuration, obj, typeof(TOptions)configureOptions)));
+ }
+ #endregion IServiceCollection extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass2 = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" });
- public static void BindCoreUntyped(this IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
+ public static void BindCoreMain(IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
- BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
if (!HasValueOrChildren(configuration))
{
return;
}
+ BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+
if (type == typeof(Program.MyClass))
{
var temp = (Program.MyClass)obj;
return;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
if (configuration["MyInt"] is string value1)
public static void BindCore(IConfiguration configuration, ref List<Program.MyClass2> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
var value = new Program.MyClass2();
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedServiceCollectionBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<TOptions>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) where TOptions : class
- {
- return global::GeneratedServiceCollectionBinder.Configure<TOptions>(services, string.Empty, configuration, configureOptions);
- }
+ using System;
+ using System.CodeDom.Compiler;
- /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<TOptions>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, string? name, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) where TOptions : class
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
{
- if (services is null)
- {
- throw new global::System.ArgumentNullException(nameof(services));
- }
-
- if (configuration is null)
+ public InterceptsLocationAttribute(string filePath, int line, int column)
{
- throw new global::System.ArgumentNullException(nameof(configuration));
}
-
- global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptions(services);
- global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IOptionsChangeTokenSource<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource<TOptions>(name, configuration));
- return global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCoreUntyped(configuration, obj, typeof(TOptions), configureOptions)));
}
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using Microsoft.Extensions.Configuration;
+ using Microsoft.Extensions.DependencyInjection;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IServiceCollection extensions.
+ /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 14, 18)]
+ public static IServiceCollection Configure<TOptions>(this IServiceCollection services, IConfiguration configuration, Action<BinderOptions>? configureOptions) where TOptions : class
+ {
+ return Configure<TOptions>(services, string.Empty, configuration, configureOptions);
+ }
+
+ /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
+ public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string? name, IConfiguration configuration, Action<BinderOptions>? configureOptions) where TOptions : class
+ {
+ if (services is null)
+ {
+ throw new ArgumentNullException(nameof(services));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ OptionsServiceCollectionExtensions.AddOptions(services);
+ services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, configuration));
+ return services.AddSingleton<Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(new Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => BindCoreMain(configuration, obj, typeof(TOptions)configureOptions)));
+ }
+ #endregion IServiceCollection extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass2 = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" });
- public static void BindCoreUntyped(this IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
+ public static void BindCoreMain(IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
- BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
if (!HasValueOrChildren(configuration))
{
return;
}
+ BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+
if (type == typeof(Program.MyClass))
{
var temp = (Program.MyClass)obj;
return;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
if (configuration["MyInt"] is string value1)
public static void BindCore(IConfiguration configuration, ref List<Program.MyClass2> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
var value = new Program.MyClass2();
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedServiceCollectionBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<TOptions>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, string? name, global::Microsoft.Extensions.Configuration.IConfiguration configuration) where TOptions : class
- {
- return global::GeneratedServiceCollectionBinder.Configure<TOptions>(services, name, configuration, configureOptions: null);
- }
+ using System;
+ using System.CodeDom.Compiler;
- /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<TOptions>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, string? name, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) where TOptions : class
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
{
- if (services is null)
- {
- throw new global::System.ArgumentNullException(nameof(services));
- }
-
- if (configuration is null)
+ public InterceptsLocationAttribute(string filePath, int line, int column)
{
- throw new global::System.ArgumentNullException(nameof(configuration));
}
-
- global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptions(services);
- global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IOptionsChangeTokenSource<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource<TOptions>(name, configuration));
- return global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCoreUntyped(configuration, obj, typeof(TOptions), configureOptions)));
}
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using Microsoft.Extensions.Configuration;
+ using Microsoft.Extensions.DependencyInjection;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IServiceCollection extensions.
+ /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 14, 18)]
+ public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string? name, IConfiguration configuration) where TOptions : class
+ {
+ return Configure<TOptions>(services, name, configuration, configureOptions: null);
+ }
+
+ /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
+ public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string? name, IConfiguration configuration, Action<BinderOptions>? configureOptions) where TOptions : class
+ {
+ if (services is null)
+ {
+ throw new ArgumentNullException(nameof(services));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ OptionsServiceCollectionExtensions.AddOptions(services);
+ services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, configuration));
+ return services.AddSingleton<Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(new Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => BindCoreMain(configuration, obj, typeof(TOptions)configureOptions)));
+ }
+ #endregion IServiceCollection extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass2 = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" });
- public static void BindCoreUntyped(this IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
+ public static void BindCoreMain(IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
- BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
if (!HasValueOrChildren(configuration))
{
return;
}
+ BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+
if (type == typeof(Program.MyClass))
{
var temp = (Program.MyClass)obj;
return;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
if (configuration["MyInt"] is string value1)
public static void BindCore(IConfiguration configuration, ref List<Program.MyClass2> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
var value = new Program.MyClass2();
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedServiceCollectionBinder
+namespace System.Runtime.CompilerServices
{
- /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<TOptions>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, string? name, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) where TOptions : class
- {
- if (services is null)
- {
- throw new global::System.ArgumentNullException(nameof(services));
- }
+ using System;
+ using System.CodeDom.Compiler;
- if (configuration is null)
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
{
- throw new global::System.ArgumentNullException(nameof(configuration));
}
-
- global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptions(services);
- global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IOptionsChangeTokenSource<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource<TOptions>(name, configuration));
- return global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton<global::Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(services, new global::Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCoreUntyped(configuration, obj, typeof(TOptions), configureOptions)));
}
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using Microsoft.Extensions.Configuration;
+ using Microsoft.Extensions.DependencyInjection;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IServiceCollection extensions.
+ /// <summary>Registers a configuration instance which TOptions will bind against.</summary>
+ [InterceptsLocationAttribute(@"src-0.cs", 14, 18)]
+ public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string? name, IConfiguration configuration, Action<BinderOptions>? configureOptions) where TOptions : class
+ {
+ if (services is null)
+ {
+ throw new ArgumentNullException(nameof(services));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ OptionsServiceCollectionExtensions.AddOptions(services);
+ services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, configuration));
+ return services.AddSingleton<Microsoft.Extensions.Options.IConfigureOptions<TOptions>>(new Microsoft.Extensions.Options.ConfigureNamedOptions<TOptions>(name, obj => BindCoreMain(configuration, obj, typeof(TOptions)configureOptions)));
+ }
+ #endregion IServiceCollection extensions.
+
+ #region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass2 = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyInt" });
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" });
- public static void BindCoreUntyped(this IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
+ public static void BindCoreMain(IConfiguration configuration, object obj, Type type, Action<BinderOptions>? configureOptions)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
- BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
if (!HasValueOrChildren(configuration))
{
return;
}
+ BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+
if (type == typeof(Program.MyClass))
{
var temp = (Program.MyClass)obj;
return;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List<int> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
if (configuration["MyInt"] is string value1)
public static void BindCore(IConfiguration configuration, ref List<Program.MyClass2> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
var value = new Program.MyClass2();
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
}
}
+
/// <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.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
{
public partial class ConfigurationBindingGeneratorTests
{
+ #region IServiceCollection extensions.
private string GetConfigureSource(string paramList) => $$"""
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
}
}
""";
+ #endregion IServiceCollection extensions.
+ #region OptionsBuilder<T> extensions.
[Fact]
public async Task Configure_T() =>
await VerifyAgainstBaselineUsingFile("Configure_T.generated.txt", GetConfigureSource("section"), extType: ExtensionClassType.ServiceCollection);
await VerifyAgainstBaselineUsingFile("BindConfiguration.generated.txt", GetSource(), extType: ExtensionClassType.OptionsBuilder);
await VerifyAgainstBaselineUsingFile("BindConfiguration.generated.txt", GetSource(@", _ => { }"), extType: ExtensionClassType.OptionsBuilder);
}
+ #endregion OptionsBuilder<T> extensions.
}
}
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
[Theory]
[InlineData(LanguageVersion.Preview)]
- [InlineData(LanguageVersion.CSharp11)]
public async Task Bind(LanguageVersion langVersion) =>
await VerifyAgainstBaselineUsingFile("Bind.generated.txt", BindCallSampleCode, langVersion, extType: ExtensionClassType.ConfigurationBinder);
await VerifyAgainstBaselineUsingFile("Collections.generated.txt", source, assessDiagnostics: (d) =>
{
- Console.WriteLine((d.Where(diag => diag.Id == Diagnostics.TypeNotSupported.Id).Count() , d.Where(diag => diag.Id == Diagnostics.PropertyNotSupported.Id).Count()));
+ Console.WriteLine((d.Where(diag => diag.Id == Diagnostics.TypeNotSupported.Id).Count(), d.Where(diag => diag.Id == Diagnostics.PropertyNotSupported.Id).Count()));
Assert.Equal(3, d.Where(diag => diag.Id == Diagnostics.TypeNotSupported.Id).Count());
Assert.Equal(6, d.Where(diag => diag.Id == Diagnostics.PropertyNotSupported.Id).Count());
});
ServiceCollection,
}
- [Fact]
- public async Task LangVersionMustBeCharp11OrHigher()
+ [Theory]
+ [InlineData(LanguageVersion.CSharp11)]
+ [InlineData(LanguageVersion.CSharp10)]
+ public async Task LangVersionMustBeCharp12OrHigher(LanguageVersion langVersion)
{
- var (d, r) = await RunGenerator(BindCallSampleCode, LanguageVersion.CSharp10);
+ var (d, r) = await RunGenerator(BindCallSampleCode, langVersion);
Assert.Empty(r);
Diagnostic diagnostic = Assert.Single(d);
Assert.True(diagnostic.Id == "SYSLIB1102");
- Assert.Contains("C# 11", diagnostic.Descriptor.Title.ToString(CultureInfo.InvariantCulture));
+ Assert.Contains("C# 12", diagnostic.Descriptor.Title.ToString(CultureInfo.InvariantCulture));
Assert.Equal(DiagnosticSeverity.Error, diagnostic.Severity);
}
Assert.Single(r);
string generatedSource = string.Join('\n', r[0].SourceText.Lines.Select(x => x.ToString()));
- Assert.Contains($"public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass0 obj) => {{ }};", generatedSource);
- Assert.Contains($"public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass1 obj, global::System.Action<global::Microsoft.Extensions.Configuration.BinderOptions>? configureOptions) => {{ }};", generatedSource);
- Assert.Contains($"public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, global::Program.MyClass2 obj) => {{ }};", generatedSource);
+ Assert.Contains("public static void Bind_ProgramMyClass0(this IConfiguration configuration, object? obj)", generatedSource);
+ Assert.Contains("public static void Bind_ProgramMyClass1(this IConfiguration configuration, object? obj, Action<BinderOptions>? configureOptions)", generatedSource);
+ Assert.Contains("public static void Bind_ProgramMyClass2(this IConfiguration configuration, string key, object? obj)", generatedSource);
Assert.Empty(d);
}
private static async Task<(ImmutableArray<Diagnostic>, ImmutableArray<GeneratedSourceResult>)> RunGenerator(
string testSourceCode,
- LanguageVersion langVersion = LanguageVersion.CSharp11,
+ LanguageVersion langVersion = LanguageVersion.Preview,
IEnumerable<Assembly>? references = null) =>
await RoslynTestUtils.RunGenerator(
new ConfigurationBindingGenerator(),
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<!-- Type not supported; property on type not suppported -->
<NoWarn>SYSLIB1100,SYSLIB1101</NoWarn>
- <!-- The SDK disables the configuration binding generator by default no matter how it was referenced, so we need to enable it here for testing. -->
+ <Features>$(Features);InterceptorsPreview</Features>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
<EnableDefaultItems>true</EnableDefaultItems>
+ <Features>$(Features);InterceptorsPreview</Features>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
<IsPackable>true</IsPackable>
<PackageDescription>Configuration support for Microsoft.Extensions.Logging.</PackageDescription>
<DefineConstants>$(DefineConstants);NO_SUPPRESS_GC_TRANSITION</DefineConstants>
<IncludePlatformAttributes>true</IncludePlatformAttributes>
<IsPackable>true</IsPackable>
+ <Features>$(Features);InterceptorsPreview</Features>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
+ <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<PackageDescription>Console logger provider implementation for Microsoft.Extensions.Logging.</PackageDescription>
</PropertyGroup>
<PropertyGroup>
<Nullable>enable</Nullable>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkMinimum)</TargetFrameworks>
- <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<DefineConstants>$(DefineConstants);BUILDING_SOURCE_GENERATOR_TESTS;ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER</DefineConstants>
- <!-- The SDK disables the configuration binding generator by default no matter how it was referenced, so we need to enable it here for testing. -->
+ <Features>$(Features);InterceptorsPreview</Features>
+ <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>