* Update binding generator to do case-insensitive config-key/property name matching, & make some formatting improvements
* Address feedback
private readonly SourceProductionContext _context;
private readonly SourceGenerationSpec _sourceGenSpec;
- // Postfix for stringValueX variables used to save config value indexer
- // results e.g. if (configuration["Key"] is string stringValue0) { ... }
- private int _parseValueCount;
-
- private bool _precedingBlockExists;
-
- private readonly SourceWriter _writer = new();
+ private bool _emitBlankLineBeforeNextStatement;
+ private bool _useFullyQualifiedNames;
+ private int _valueSuffixIndex;
private static readonly Regex s_arrayBracketsRegex = new(Regex.Escape("[]"));
- public bool _useFullyQualifiedNames { get; private set; }
+ private readonly SourceWriter _writer = new();
public Emitter(SourceProductionContext context, SourceGenerationSpec sourceGenSpec)
{
return;
}
- _writer.WriteLine(@"// <auto-generated/>
-#nullable enable
-");
+ _writer.WriteBlock("""
+ // <auto-generated/>
+ #nullable enable
+ #pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
+ """);
+ _writer.WriteBlankLine();
+
_useFullyQualifiedNames = true;
EmitBinder_ConfigurationBinder();
EmitBinder_Extensions_OptionsBuilder();
_context.AddSource($"{Identifier.GeneratedConfigurationBinder}.g.cs", _writer.ToSourceText());
}
- private void EmitBindLogicFromRootMethod(TypeSpec type, string expressionForMemberAccess, InitializationKind initKind)
- {
- TypeSpecKind kind = type.SpecKind;
-
- if (kind is TypeSpecKind.Nullable)
- {
- EmitBindLogicFromRootMethod(((NullableSpec)type).UnderlyingType, expressionForMemberAccess, initKind);
- }
- else
- {
- if (type is ParsableFromStringSpec stringParsableType)
- {
- if (initKind is InitializationKind.Declaration)
- {
- EmitCastToIConfigurationSection();
- _writer.WriteLine($"{GetTypeDisplayString(type)} {expressionForMemberAccess} = default!;");
- }
- else
- {
- EmitCastToIConfigurationSection();
- }
-
- EmitBindLogicFromString(stringParsableType, Expression.sectionValue, Expression.sectionPath);
- }
- else
- {
- EmitBindCoreCall(type, expressionForMemberAccess, Identifier.configuration, initKind);
- }
- }
- }
-
private void EmitBindCoreCall(
TypeSpec type,
- string expressionForMemberAccess,
- string expressionForConfigArg,
- InitializationKind initKind)
+ string memberAccessExpr,
+ string configArgExpr,
+ InitializationKind initKind,
+ Action<string>? writeOnSuccess = null)
{
Debug.Assert(type.CanInitialize);
- string tempVarName = GetIncrementalVarName(Identifier.temp);
+ if (!type.NeedsMemberBinding)
+ {
+ EmitObjectInit(memberAccessExpr, initKind);
+ return;
+ }
+
+ string tempIdentifier = GetIncrementalIdentifier(Identifier.temp);
if (initKind is InitializationKind.AssignmentWithNullCheck)
{
- _writer.WriteLine($"{type.MinimalDisplayString} {tempVarName} = {expressionForMemberAccess};");
- EmitObjectInit(type, tempVarName, InitializationKind.AssignmentWithNullCheck);
- EmitBindCoreCall(tempVarName);
+ _writer.WriteLine($"{type.MinimalDisplayString} {tempIdentifier} = {memberAccessExpr};");
+ EmitBindCoreCall(tempIdentifier, InitializationKind.AssignmentWithNullCheck);
}
else if (initKind is InitializationKind.None && type.IsValueType)
{
- EmitObjectInit(type, tempVarName, InitializationKind.Declaration);
- _writer.WriteLine($@"{Identifier.BindCore}({expressionForConfigArg}, ref {tempVarName}, {Identifier.binderOptions});");
- _writer.WriteLine($"{expressionForMemberAccess} = {tempVarName};");
+ EmitBindCoreCall(tempIdentifier, InitializationKind.Declaration);
+ _writer.WriteLine($"{memberAccessExpr} = {tempIdentifier};");
}
else
{
- EmitObjectInit(type, expressionForMemberAccess, initKind);
- EmitBindCoreCall(expressionForMemberAccess);
+ EmitBindCoreCall(memberAccessExpr, initKind);
}
- void EmitBindCoreCall(string varName)
+ void EmitBindCoreCall(string objExpression, InitializationKind initKind)
{
- string bindCoreCall = $@"{GetHelperMethodDisplayString(Identifier.BindCore)}({expressionForConfigArg}, ref {varName}, {Identifier.binderOptions});";
+ string methodDisplayString = GetHelperMethodDisplayString(nameof(MethodsToGen_CoreBindingHelper.BindCore));
+ string bindCoreCall = $@"{methodDisplayString}({configArgExpr}, ref {objExpression}, {Identifier.binderOptions});";
+
+ EmitObjectInit(objExpression, initKind);
_writer.WriteLine(bindCoreCall);
+ writeOnSuccess?.Invoke(objExpression);
+ }
+
+ void EmitObjectInit(string objExpression, InitializationKind initKind)
+ {
+ if (initKind is not InitializationKind.None)
+ {
+ this.EmitObjectInit(type, objExpression, initKind, configArgExpr);
+ }
}
}
- public void EmitBindLogicFromString(
+ private void EmitBindLogicFromString(
ParsableFromStringSpec type,
- string configStringValueExpr,
- string configValuePathExpr,
- Action<string>? writeOnSuccess = null,
- bool isCollectionElement = false)
+ string sectionValueExpr,
+ string sectionPathExpr,
+ Action<string>? writeOnSuccess,
+ bool checkForNullSectionValue,
+ bool useIncrementalStringValueIdentifier)
{
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
Debug.Assert(typeKind is not StringParsableTypeKind.None);
- string stringValueVarName = GetIncrementalVarName(Identifier.stringValue);
- string parsedValueExpr;
+ string nonNull_StringValue_Identifier = useIncrementalStringValueIdentifier ? GetIncrementalIdentifier(Identifier.value) : Identifier.value;
+ string stringValueToParse_Expr = checkForNullSectionValue ? nonNull_StringValue_Identifier : sectionValueExpr;
- if (typeKind is StringParsableTypeKind.ConfigValue)
+ string parsedValueExpr;
+ if (typeKind is StringParsableTypeKind.AssignFromSectionValue)
{
- if (isCollectionElement)
- {
- parsedValueExpr = stringValueVarName;
- }
- else
- {
- writeOnSuccess?.Invoke(configStringValueExpr);
- return;
- }
+ parsedValueExpr = stringValueToParse_Expr;
}
else
{
string helperMethodDisplayString = GetHelperMethodDisplayString(type.ParseMethodName);
- parsedValueExpr = $"{helperMethodDisplayString}({stringValueVarName}, () => {configValuePathExpr})";
+ parsedValueExpr = $"{helperMethodDisplayString}({stringValueToParse_Expr}, () => {sectionPathExpr})";
}
- _writer.WriteBlockStart($"if ({configStringValueExpr} is string {stringValueVarName})");
- writeOnSuccess?.Invoke(parsedValueExpr);
- _writer.WriteBlockEnd();
-
- return;
+ if (!checkForNullSectionValue)
+ {
+ writeOnSuccess?.Invoke(parsedValueExpr);
+ }
+ else
+ {
+ _writer.WriteBlockStart($"if ({sectionValueExpr} is string {nonNull_StringValue_Identifier})");
+ writeOnSuccess?.Invoke(parsedValueExpr);
+ _writer.WriteBlockEnd();
+ }
}
- private bool EmitObjectInit(TypeSpec type, string expressionForMemberAccess, InitializationKind initKind)
+ private bool EmitObjectInit(TypeSpec type, string memberAccessExpr, InitializationKind initKind, string configArgExpr)
{
- Debug.Assert(type.CanInitialize);
-
- if (initKind is InitializationKind.None)
- {
- return true;
- }
+ Debug.Assert(type.CanInitialize && initKind is not InitializationKind.None);
- string expressionForInit;
+ string initExpr;
CollectionSpec? collectionType = type as CollectionSpec;
string effectiveDisplayString = GetTypeDisplayString(type);
{
if (collectionType is EnumerableSpec { InitializationStrategy: InitializationStrategy.Array })
{
- expressionForInit = $"new {s_arrayBracketsRegex.Replace(effectiveDisplayString, "[0]", 1)}";
+ initExpr = $"new {s_arrayBracketsRegex.Replace(effectiveDisplayString, "[0]", 1)}";
}
else
{
effectiveDisplayString = GetTypeDisplayString(collectionType.ConcreteType ?? collectionType);
- expressionForInit = $"new {effectiveDisplayString}()";
+ initExpr = $"new {effectiveDisplayString}()";
}
}
else if (type.InitializationStrategy is InitializationStrategy.ParameterlessConstructor)
{
- expressionForInit = $"new {effectiveDisplayString}()";
+ initExpr = $"new {effectiveDisplayString}()";
}
else
{
Debug.Assert(type.InitializationStrategy is InitializationStrategy.ParameterizedConstructor);
- string expressionForConfigSection = initKind is InitializationKind.Declaration ? Identifier.configuration : Identifier.section;
- string initMethodIdentifier = GetHelperMethodDisplayString(((ObjectSpec)type).InitializeMethodDisplayString);
- expressionForInit = $"{initMethodIdentifier}({expressionForConfigSection}, {Identifier.binderOptions});";
+ string initMethodIdentifier = GetInitalizeMethodDisplayString(((ObjectSpec)type));
+ initExpr = $"{initMethodIdentifier}({configArgExpr}, {Identifier.binderOptions})";
}
if (initKind == InitializationKind.Declaration)
{
- Debug.Assert(!expressionForMemberAccess.Contains("."));
- _writer.WriteLine($"var {expressionForMemberAccess} = {expressionForInit};");
+ Debug.Assert(!memberAccessExpr.Contains("."));
+ _writer.WriteLine($"var {memberAccessExpr} = {initExpr};");
}
else if (initKind == InitializationKind.AssignmentWithNullCheck)
{
{
if (collectionType.InitializationStrategy is InitializationStrategy.ParameterizedConstructor)
{
- _writer.WriteLine($"{expressionForMemberAccess} = {expressionForMemberAccess} is null ? {expressionForInit} : new {effectiveDisplayString}({expressionForMemberAccess});");
+ _writer.WriteLine($"{memberAccessExpr} = {memberAccessExpr} is null ? {initExpr} : new {effectiveDisplayString}({memberAccessExpr});");
}
else
{
- _writer.WriteLine($"{expressionForMemberAccess} = {expressionForMemberAccess} is null ? {expressionForInit} : {expressionForMemberAccess}.{collectionType.ToEnumerableMethodCall!};");
+ _writer.WriteLine($"{memberAccessExpr} = {memberAccessExpr} is null ? {initExpr} : {memberAccessExpr}.{collectionType.ToEnumerableMethodCall!};");
}
}
else
{
- _writer.WriteLine($"{expressionForMemberAccess} ??= {expressionForInit};");
+ _writer.WriteLine($"{memberAccessExpr} ??= {initExpr};");
}
}
else
{
Debug.Assert(initKind is InitializationKind.SimpleAssignment);
- _writer.WriteLine($"{expressionForMemberAccess} = {expressionForInit};");
+ _writer.WriteLine($"{memberAccessExpr} = {initExpr};");
}
return true;
}
- public void EmitCastToIConfigurationSection()
+ private void EmitCastToIConfigurationSection()
{
string sectionTypeDisplayString;
string exceptionTypeDisplayString;
""");
}
- public void EmitIConfigurationHasValueOrChildrenCheck(bool voidReturn)
+ private void EmitIConfigurationHasValueOrChildrenCheck(bool voidReturn)
{
string returnPostfix = voidReturn ? string.Empty : " null";
string methodDisplayString = GetHelperMethodDisplayString(Identifier.HasValueOrChildren);
if (IsNullable(type, out ITypeSymbol? underlyingType))
{
spec = TryGetTypeSpec(underlyingType, Diagnostics.NullableUnderlyingTypeNotSupported, out TypeSpec? underlyingTypeSpec)
- ? new NullableSpec(type) { Location = location, UnderlyingType = underlyingTypeSpec }
+ ? new NullableSpec(type, underlyingTypeSpec)
: null;
}
else if (IsParsableFromString(type, out StringParsableTypeKind specialTypeKind))
{
- ParsableFromStringSpec stringParsableSpec = new(type)
- {
- Location = location,
- StringParsableTypeKind = specialTypeKind
- };
+ ParsableFromStringSpec stringParsableSpec = new(type) { StringParsableTypeKind = specialTypeKind };
- if (stringParsableSpec.StringParsableTypeKind is not StringParsableTypeKind.ConfigValue)
+ if (stringParsableSpec.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue)
{
_sourceGenSpec.PrimitivesForHelperGen.Add(stringParsableSpec);
}
}
else if (IsSupportedArrayType(type, location))
{
- spec = CreateArraySpec((type as IArrayTypeSymbol)!, location);
- RegisterBindCoreGenType(spec);
+ spec = CreateArraySpec((type as IArrayTypeSymbol));
}
else if (IsCollection(type))
{
spec = CreateCollectionSpec((INamedTypeSymbol)type, location);
- RegisterBindCoreGenType(spec);
}
else if (SymbolEqualityComparer.Default.Equals(type, _typeSymbols.IConfigurationSection))
{
- spec = new ConfigurationSectionSpec(type) { Location = location };
+ spec = new ConfigurationSectionSpec(type);
}
else if (type is INamedTypeSymbol namedType)
{
_sourceGenSpec.TypeNamespaces.Add("System.Collections.Generic");
spec = CreateObjectSpec(namedType, location);
- RegisterBindCoreGenType(spec);
}
if (spec is null)
}
return _createdSpecs[type] = spec;
-
- void RegisterBindCoreGenType(TypeSpec? spec)
- {
- if (spec is not null)
- {
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, spec);
- }
- }
}
private void RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper method, TypeSpec type)
private void RegisterTypeForBindCoreUntypedGen(TypeSpec typeSpec)
{
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, typeSpec);
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCoreUntyped, typeSpec);
+ if (typeSpec.NeedsMemberBinding)
+ {
+ RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, typeSpec);
+ RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCoreUntyped, typeSpec);
+ }
}
private static bool IsNullable(ITypeSymbol type, [NotNullWhen(true)] out ITypeSymbol? underlyingType)
case SpecialType.System_String:
case SpecialType.System_Object:
{
- typeKind = StringParsableTypeKind.ConfigValue;
+ typeKind = StringParsableTypeKind.AssignFromSectionValue;
return true;
}
case SpecialType.System_Boolean:
return true;
}
- private EnumerableSpec? CreateArraySpec(IArrayTypeSymbol arrayType, Location? location)
+ private EnumerableSpec? CreateArraySpec(IArrayTypeSymbol arrayType)
{
if (!TryGetTypeSpec(arrayType.ElementType, Diagnostics.ElementTypeNotSupported, out TypeSpec elementSpec))
{
EnumerableSpec spec = new EnumerableSpec(arrayType)
{
- Location = location,
ElementType = elementSpec,
ConcreteType = listSpec,
InitializationStrategy = InitializationStrategy.Array,
};
Debug.Assert(spec.CanInitialize);
+ RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, spec);
+
return spec;
}
if (spec is not null)
{
+ RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, spec);
spec.InitExceptionMessage ??= spec.ElementType.InitExceptionMessage;
}
DictionarySpec spec = new(type)
{
- Location = location,
KeyType = (ParsableFromStringSpec)keySpec,
ElementType = elementSpec,
InitializationStrategy = constructionStrategy,
return null;
}
- RegisterHasChildrenHelperForGenIfRequired(elementSpec);
+ Register_AsConfigWithChildren_HelperForGen_IfRequired(elementSpec);
EnumerableSpec spec = new(type)
{
- Location = location,
ElementType = elementSpec,
InitializationStrategy = constructionStrategy,
PopulationStrategy = populationStrategy,
private ObjectSpec? CreateObjectSpec(INamedTypeSymbol type, Location? location)
{
// Add spec to cache before traversing properties to avoid stack overflow.
- ObjectSpec objectSpec = new(type) { Location = location };
+ ObjectSpec objectSpec = new(type);
_createdSpecs.Add(type, objectSpec);
string typeName = objectSpec.Name;
{
PropertySpec spec = new(property) { Type = propertyTypeSpec, ConfigurationKeyName = configKeyName };
objectSpec.Properties[propertyName] = spec;
- RegisterHasChildrenHelperForGenIfRequired(propertyTypeSpec);
+ Register_AsConfigWithChildren_HelperForGen_IfRequired(propertyTypeSpec);
}
}
}
Debug.Assert((objectSpec.CanInitialize && objectSpec.InitExceptionMessage is null) ||
(!objectSpec.CanInitialize && objectSpec.InitExceptionMessage is not null));
+ if (objectSpec.NeedsMemberBinding)
+ {
+ RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, objectSpec);
+ }
+
return objectSpec;
}
- private void RegisterHasChildrenHelperForGenIfRequired(TypeSpec type)
+ private void Register_AsConfigWithChildren_HelperForGen_IfRequired(TypeSpec type)
{
if (type.SpecKind is TypeSpecKind.Object or
TypeSpecKind.Enumerable or
TypeSpecKind.Dictionary)
{
- _sourceGenSpec.ShouldEmitHasChildren = true;
+ _sourceGenSpec.MethodsToGen_CoreBindingHelper |= MethodsToGen_CoreBindingHelper.AsConfigWithChildren;
}
}
return;
}
- _writer.WriteLine("/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>");
- _writer.WriteBlockStart($"internal static class {Identifier.GeneratedConfigurationBinder}");
+ _emitBlankLineBeforeNextStatement = false;
+ EmitRootBindingClassBlockStart(Identifier.GeneratedConfigurationBinder);
EmitGetMethods();
EmitGetValueMethods();
EmitBindMethods_ConfigurationBinder();
_writer.WriteBlockEnd();
-
- _precedingBlockExists = true;
+ _emitBlankLineBeforeNextStatement = true;
}
private void EmitGetMethods()
{
- const string expressionForGetCore = $"{FullyQualifiedDisplayString.CoreBindingHelper}.{Identifier.GetCore}";
+ const string expressionForGetCore = $"{FullyQualifiedDisplayString.CoreBindingHelper}.{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))
private void EmitGetValueMethods()
{
- const string expressionForGetValueCore = $"{FullyQualifiedDisplayString.CoreBindingHelper}.{Identifier.GetValueCore}";
+ const string expressionForGetValueCore = $"{FullyQualifiedDisplayString.CoreBindingHelper}.{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))
EmitMethodImplementation(
type,
additionalParams: $"string {Identifier.key}, {GetObjParameter(type)}",
- configExpression: $"{Identifier.configuration}.{Identifier.GetSection}({Identifier.key})",
+ configExpression: $"{Expression.configurationGetSection}({Identifier.key})",
configureOptions: false);
}
}
void EmitMethodImplementation(TypeSpec type, string additionalParams, string configExpression, bool configureOptions)
{
string binderOptionsArg = configureOptions ? $"{Expression.GetBinderOptions}({Identifier.configureOptions})" : $"{Identifier.binderOptions}: null";
- string returnExpression = type.CanInitialize
- ? $"{FullyQualifiedDisplayString.CoreBindingHelper}.{Identifier.BindCore}({configExpression}, ref {Identifier.obj}, {binderOptionsArg})"
- : GetInitException(type.InitExceptionMessage);
+
+ string returnExpression;
+ if (type.CanInitialize)
+ {
+ returnExpression = type.NeedsMemberBinding
+ ? $"{FullyQualifiedDisplayString.CoreBindingHelper}.{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configExpression}, ref {Identifier.obj}, {binderOptionsArg})"
+ : "{ }";
+ }
+ 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}) => "
private void Emit_CoreBindingHelper()
{
- Debug.Assert(_precedingBlockExists);
+ Debug.Assert(_emitBlankLineBeforeNextStatement);
_writer.WriteBlankLine();
- _precedingBlockExists = false;
+ _emitBlankLineBeforeNextStatement = false;
_writer.WriteBlockStart($"namespace {ProjectName}");
EmitHelperUsingStatements();
_writer.WriteBlankLine();
- _writer.WriteLine("/// <summary>Provide core binding logic.</summary>");
- _writer.WriteBlockStart($"internal static class {Identifier.CoreBindingHelper}");
+ _writer.WriteBlock($$"""
+ /// <summary>Provide core binding logic.</summary>
+ {{GetGeneratedCodeAttributeSrc()}}
+ file static class {{Identifier.CoreBindingHelper}}
+ {
+ """);
+ EmitConfigurationKeyCaches();
EmitGetCoreMethod();
EmitGetValueCoreMethod();
EmitBindCoreUntypedMethod();
}
}
+ private void EmitConfigurationKeyCaches()
+ {
+ if (!_sourceGenSpec.TypesForGen_CoreBindingHelper_Methods.TryGetValue(MethodsToGen_CoreBindingHelper.BindCore, out HashSet<TypeSpec> targetTypes))
+ {
+ return;
+ }
+
+ foreach (TypeSpec type in targetTypes)
+ {
+ if (type is not ObjectSpec objectType)
+ {
+ continue;
+ }
+
+ HashSet<string> keys = new(objectType.ConstructorParameters.Select(m => GetCacheElement(m)));
+ keys.UnionWith(objectType.Properties.Values.Select(m => GetCacheElement(m)));
+ static string GetCacheElement(MemberSpec member) => $@"""{member.ConfigurationKeyName}""";
+
+ 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} }});");
+ }
+
+ _emitBlankLineBeforeNextStatement = true;
+ }
+
private void EmitGetCoreMethod()
{
if (!_sourceGenSpec.TypesForGen_CoreBindingHelper_Methods.TryGetValue(MethodsToGen_CoreBindingHelper.GetCore, out HashSet<TypeSpec>? types))
return;
}
- _writer.WriteBlockStart($"public static object? {Identifier.GetCore}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, Action<{Identifier.BinderOptions}>? {Identifier.configureOptions})");
+ EmitBlankLineIfRequired();
+ _writer.WriteBlockStart($"public static object? {nameof(MethodsToGen_CoreBindingHelper.GetCore)}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, Action<{Identifier.BinderOptions}>? {Identifier.configureOptions})");
EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
foreach (TypeSpec type in types)
{
+ TypeSpecKind kind = type.SpecKind;
+
_writer.WriteBlockStart($"if (type == typeof({type.MinimalDisplayString}))");
- if (type.InitializationStrategy is InitializationStrategy.None || !EmitInitException(type))
+ if (type is ParsableFromStringSpec stringParsableType)
{
- EmitBindLogicFromRootMethod(type, Identifier.obj, InitializationKind.Declaration);
+ EmitCastToIConfigurationSection();
+ EmitBindLogicFromString(
+ stringParsableType,
+ Expression.sectionValue,
+ Expression.sectionPath,
+ writeOnSuccess: parsedValueExpr => _writer.WriteLine($"return {parsedValueExpr};"),
+ checkForNullSectionValue: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue,
+ useIncrementalStringValueIdentifier: false);
+ }
+ else if (!EmitInitException(type))
+ {
+ EmitBindCoreCall(type, Identifier.obj, Identifier.configuration, InitializationKind.Declaration);
_writer.WriteLine($"return {Identifier.obj};");
}
Emit_NotSupportedException_TypeNotDetectedAsInput();
_writer.WriteBlockEnd();
- _precedingBlockExists = true;
+ _emitBlankLineBeforeNextStatement = true;
}
private void EmitGetValueCoreMethod()
}
EmitBlankLineIfRequired();
-
- _writer.WriteBlockStart($"public static object? {Identifier.GetValueCore}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, string {Identifier.key})");
+ _writer.WriteBlockStart($"public static object? {nameof(MethodsToGen_CoreBindingHelper.GetValueCore)}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, string {Identifier.key})");
EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
+ _writer.WriteLine($@"{Identifier.IConfigurationSection} {Identifier.section} = {GetSectionFromConfigurationExpression(Identifier.key, addQuotes: false)};");
+ _writer.WriteBlankLine();
- _writer.WriteLine($"{Identifier.IConfigurationSection} {Identifier.section} = {Identifier.configuration}.{Identifier.GetSection}({Identifier.key});");
+ _writer.WriteBlock($$"""
+ if ({{Expression.sectionValue}} is not string {{Identifier.value}})
+ {
+ return null;
+ }
+ """);
_writer.WriteBlankLine();
foreach (TypeSpec type in targetTypes)
{
- ParsableFromStringSpec effectiveType = (ParsableFromStringSpec)((type as NullableSpec)?.UnderlyingType ?? type);
_writer.WriteBlockStart($"if ({Identifier.type} == typeof({type.MinimalDisplayString}))");
EmitBindLogicFromString(
- effectiveType,
- Expression.sectionValue,
- Expression.sectionPath,
- writeOnSuccess: (parsedValueExpr) => _writer.WriteLine($"return {parsedValueExpr};"));
+ (ParsableFromStringSpec)type.EffectiveType,
+ Identifier.value,
+ Expression.sectionPath,
+ writeOnSuccess: (parsedValueExpr) => _writer.WriteLine($"return {parsedValueExpr};"),
+ checkForNullSectionValue: false,
+ useIncrementalStringValueIdentifier: false);
_writer.WriteBlockEnd();
_writer.WriteBlankLine();
_writer.WriteLine("return null;");
_writer.WriteBlockEnd();
- _precedingBlockExists = true;
+ _emitBlankLineBeforeNextStatement = true;
}
private void EmitBindCoreUntypedMethod()
EmitBlankLineIfRequired();
- _writer.WriteBlockStart($"public static void {Identifier.BindCoreUntyped}(this {Identifier.IConfiguration} {Identifier.configuration}, object {Identifier.obj}, Type {Identifier.type}, {MinimalDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions})");
+ _writer.WriteBlockStart($"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCoreUntyped)}(this {Identifier.IConfiguration} {Identifier.configuration}, object {Identifier.obj}, Type {Identifier.type}, {MinimalDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions})");
EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
{
_writer.WriteBlockStart($"if (type == typeof({type.MinimalDisplayString}))");
- if (type.InitializationStrategy is InitializationStrategy.None || !EmitInitException(type))
+ TypeSpec effectiveType = type.EffectiveType;
+ if (!EmitInitException(effectiveType))
{
- _writer.WriteLine($"var {Identifier.temp} = ({type.MinimalDisplayString}){Identifier.obj};");
- EmitBindLogicFromRootMethod(type, Identifier.temp, InitializationKind.None);
+ _writer.WriteLine($"var {Identifier.temp} = ({effectiveType.MinimalDisplayString}){Identifier.obj};");
+ EmitBindCoreCall(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
_writer.WriteLine($"return;");
}
Emit_NotSupportedException_TypeNotDetectedAsInput();
_writer.WriteBlockEnd();
- _precedingBlockExists = true;
+ _emitBlankLineBeforeNextStatement = true;
}
private void EmitBindCoreMethods()
foreach (TypeSpec type in targetTypes)
{
- if (type.SpecKind is TypeSpecKind.ParsableFromString)
- {
- continue;
- }
-
+ Debug.Assert(type.NeedsMemberBinding);
EmitBlankLineIfRequired();
EmitBindCoreMethod(type);
}
private void EmitBindCoreMethod(TypeSpec type)
{
- if (!type.CanInitialize)
+ Debug.Assert(type.CanInitialize);
+
+ string objParameterExpression = $"ref {type.MinimalDisplayString} {Identifier.obj}";
+ _writer.WriteBlockStart(@$"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)
{
- return;
+ if (effectiveType.InitializationStrategy is InitializationStrategy.Array)
+ {
+ Debug.Assert(type == effectiveType);
+ EmitPopulationImplForArray((EnumerableSpec)type);
+ }
+ else
+ {
+ EmitPopulationImplForEnumerableWithAdd(enumerable);
+ }
+ }
+ else if (effectiveType is DictionarySpec dictionary)
+ {
+ EmitBindCoreImplForDictionary(dictionary);
+ }
+ else
+ {
+ EmitBindCoreImplForObject((ObjectSpec)effectiveType);
}
- string objParameterExpression = $"ref {type.MinimalDisplayString} {Identifier.obj}";
- _writer.WriteBlockStart(@$"public static void {Identifier.BindCore}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
- EmitBindCoreImpl(type);
_writer.WriteBlockEnd();
}
private void EmitInitializeMethod(ObjectSpec type)
{
Debug.Assert(type.CanInitialize);
-
List<ParameterSpec> ctorParams = type.ConstructorParameters;
- IEnumerable<PropertySpec> initOnlyProps = type.Properties.Values.Where(prop => prop.SetOnInit);
+ IEnumerable<PropertySpec> initOnlyProps = type.Properties.Values.Where(prop => prop is { SetOnInit: true });
+ List<string> ctorArgList = new();
string displayString = type.MinimalDisplayString;
- _writer.WriteBlockStart($"public static {displayString} {type.InitializeMethodDisplayString}({Identifier.IConfiguration} {Identifier.configuration}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
+ _writer.WriteBlockStart($"public static {type.MinimalDisplayString} {GetInitalizeMethodDisplayString(type)}({Identifier.IConfiguration} {Identifier.configuration}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
+ _emitBlankLineBeforeNextStatement = false;
foreach (ParameterSpec parameter in ctorParams)
{
- if (!parameter.HasExplicitDefaultValue)
+ string name = parameter.Name;
+ string argExpr = parameter.RefKind switch
{
- _writer.WriteLine($@"({parameter.Type.MinimalDisplayString} {Identifier.Value}, bool {Identifier.HasConfig}) {parameter.Name} = ({parameter.DefaultValue}, false);");
- }
- else
- {
- _writer.WriteLine($@"{parameter.Type.MinimalDisplayString} {parameter.Name} = {parameter.DefaultValue};");
- }
- }
-
- foreach (PropertySpec property in initOnlyProps)
- {
- if (property.MatchingCtorParam is null)
- {
- _writer.WriteLine($@"{property.Type.MinimalDisplayString} {property.Name} = default!;");
- }
- }
-
- _writer.WriteBlankLine();
-
- _writer.WriteBlock($$"""
- foreach ({{Identifier.IConfigurationSection}} {{Identifier.section}} in {{Identifier.configuration}}.{{Identifier.GetChildren}}())
- {
- switch ({{Expression.sectionKey}})
- {
- """);
-
- List<string> argumentList = new();
+ RefKind.None => name,
+ RefKind.Ref => $"ref {name}",
+ RefKind.Out => "out _",
+ RefKind.In => $"in {name}",
+ _ => throw new InvalidOperationException()
+ };
- foreach (ParameterSpec parameter in ctorParams)
- {
- EmitMemberBindLogic(parameter.Name, parameter.Type, parameter.ConfigurationKeyName, configValueMustExist: !parameter.HasExplicitDefaultValue);
- argumentList.Add(GetExpressionForArgument(parameter));
+ ctorArgList.Add(argExpr);
+ EmitBindImplForMember(parameter);
}
foreach (PropertySpec property in initOnlyProps)
{
if (property.ShouldBind() && property.MatchingCtorParam is null)
{
- EmitMemberBindLogic(property.Name, property.Type, property.ConfigurationKeyName);
+ EmitBindImplForMember(property);
}
}
- EmitSwitchDefault("continue;", addBreak: false);
-
- _writer.WriteBlockEnd();
- _writer.WriteBlockEnd();
-
- _precedingBlockExists = true;
-
- foreach (ParameterSpec parameter in ctorParams)
- {
- if (!parameter.HasExplicitDefaultValue)
- {
- string parameterName = parameter.Name;
-
- EmitBlankLineIfRequired();
- _writer.WriteBlock($$"""
- if (!{{parameterName}}.{{Identifier.HasConfig}})
- {
- throw new {{GetInvalidOperationDisplayName()}}("{{string.Format(ExceptionMessages.ParameterHasNoMatchingConfig, type.Name, parameterName)}}");
- }
- """);
- }
- }
-
- EmitBlankLineIfRequired();
-
- string returnExpression = $"return new {displayString}({string.Join(", ", argumentList)})";
+ string returnExpression = $"return new {displayString}({string.Join(", ", ctorArgList)})";
if (!initOnlyProps.Any())
{
_writer.WriteLine($"{returnExpression};");
foreach (PropertySpec property in initOnlyProps)
{
string propertyName = property.Name;
- string initValue = propertyName + (property.MatchingCtorParam is null or ParameterSpec { HasExplicitDefaultValue: true } ? string.Empty : $".{Identifier.Value}");
- _writer.WriteLine($@"{propertyName} = {initValue},");
+ _writer.WriteLine($@"{propertyName} = {propertyName},");
}
_writer.WriteBlockEnd(";");
}
// End method.
_writer.WriteBlockEnd();
+ _emitBlankLineBeforeNextStatement = true;
- void EmitMemberBindLogic(string memberName, TypeSpec memberType, string configurationKeyName, bool configValueMustExist = false)
+ void EmitBindImplForMember(MemberSpec member)
{
- string lhs = memberName + (configValueMustExist ? $".{Identifier.Value}" : string.Empty);
-
- _writer.WriteLine($@"case ""{configurationKeyName}"":");
- _writer.Indentation++;
- _writer.WriteBlockStart();
+ TypeSpec memberType = member.Type;
+ bool errorOnFailedBinding = member.ErrorOnFailedBinding;
- EmitMemberBindLogicCore(memberType, lhs);
+ string parsedMemberIdentifierDeclarationPrefix = $"{memberType.MinimalDisplayString} {member.Name}";
+ string parsedMemberIdentifier;
- if (configValueMustExist)
+ if (memberType is ParsableFromStringSpec { StringParsableTypeKind: StringParsableTypeKind.AssignFromSectionValue })
{
- _writer.WriteLine($"{memberName}.{Identifier.HasConfig} = true;");
- }
-
- _writer.WriteBlockEnd();
- _writer.WriteLine("break;");
- _writer.Indentation--;
-
- void EmitMemberBindLogicCore(TypeSpec type, string lhs)
- {
- TypeSpecKind kind = type.SpecKind;
+ parsedMemberIdentifier = parsedMemberIdentifierDeclarationPrefix;
- if (kind is TypeSpecKind.Nullable)
+ if (errorOnFailedBinding)
{
- EmitMemberBindLogicCore(((NullableSpec)type).UnderlyingType, lhs);
+ string condition = $@" if ({Identifier.configuration}[""{member.ConfigurationKeyName}""] is not {memberType.MinimalDisplayString} {member.Name})";
+ EmitThrowBlock(condition);
+ _writer.WriteBlankLine();
+ return;
}
- else if (type is ParsableFromStringSpec stringParsableType)
+ }
+ else
+ {
+ parsedMemberIdentifier = member.Name;
+
+ string declarationSuffix;
+ if (errorOnFailedBinding)
{
- EmitBindLogicFromString(
- stringParsableType,
- Expression.sectionValue,
- Expression.sectionPath,
- (parsedValueExpr) => _writer.WriteLine($"{lhs} = {parsedValueExpr}!;"));
+ declarationSuffix = ";";
}
- else if (!EmitInitException(type))
+ else
{
- EmitBindCoreCall(type, lhs, Identifier.section, InitializationKind.SimpleAssignment);
+ string bangExpr = memberType.IsValueType ? string.Empty : "!";
+ declarationSuffix = memberType.CanInitialize
+ ? $" = {member.DefaultValueExpr}{bangExpr};"
+ : ";";
}
+
+ string parsedMemberIdentifierDeclaration = $"{parsedMemberIdentifierDeclarationPrefix}{declarationSuffix}";
+ _writer.WriteLine(parsedMemberIdentifierDeclaration);
+ _emitBlankLineBeforeNextStatement = false;
}
- }
- static string GetExpressionForArgument(ParameterSpec parameter)
- {
- string name = parameter.Name + (parameter.HasExplicitDefaultValue ? string.Empty : $".{Identifier.Value}");
+ bool canBindToMember = this.EmitBindImplForMember(
+ member,
+ parsedMemberIdentifier,
+ sectionPathExpr: GetSectionPathFromConfigurationExpression(member.ConfigurationKeyName),
+ canSet: true);
- return parameter.RefKind switch
+ if (canBindToMember)
{
- RefKind.None => name,
- RefKind.Ref => $"ref {name}",
- RefKind.Out => "out _",
- RefKind.In => $"in {name}",
- _ => throw new InvalidOperationException()
- };
+ if (errorOnFailedBinding)
+ {
+ // Add exception logic for parameter ctors; must be present in configuration object.
+ EmitThrowBlock(condition: "else");
+ }
+
+ _writer.WriteBlankLine();
+ }
+
+ void EmitThrowBlock(string condition) =>
+ _writer.WriteBlock($$"""
+ {{condition}}
+ {
+ throw new {{GetInvalidOperationDisplayName()}}("{{string.Format(ExceptionMessages.ParameterHasNoMatchingConfig, type.Name, member.Name)}}");
+ }
+ """);
}
}
private void EmitHelperMethods()
{
+ if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.BindCore))
+ {
+ EmitValidateConfigurationKeysMethod();
+ }
+
if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.BindCoreUntyped | MethodsToGen_CoreBindingHelper.GetCore))
{
_writer.WriteBlankLine();
EmitHasValueOrChildrenMethod();
_writer.WriteBlankLine();
- EmitHasChildrenMethod();
- _precedingBlockExists = true;
+ EmitAsConfigWithChildrenMethod();
+ _emitBlankLineBeforeNextStatement = true;
}
- else if (_sourceGenSpec.ShouldEmitHasChildren)
+ else if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.AsConfigWithChildren))
{
_writer.WriteBlankLine();
- EmitHasChildrenMethod();
- _precedingBlockExists = true;
+ EmitAsConfigWithChildrenMethod();
+ _emitBlankLineBeforeNextStatement = true;
}
if (ShouldEmitMethods(
{
_writer.WriteBlankLine();
EmitGetBinderOptionsHelper();
- _precedingBlockExists = true;
+ _emitBlankLineBeforeNextStatement = true;
}
foreach (ParsableFromStringSpec type in _sourceGenSpec.PrimitivesForHelperGen)
}
}
+ private void EmitValidateConfigurationKeysMethod()
+ {
+ const string keysIdentifier = "keys";
+ string exceptionMessage = string.Format(ExceptionMessages.MissingConfig, Identifier.ErrorOnUnknownConfiguration, Identifier.BinderOptions, $"{{{Identifier.type}}}", $@"{{string.Join("", "", {Identifier.temp})}}");
+
+ EmitBlankLineIfRequired();
+ _writer.WriteBlock($$"""
+ /// <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}})
+ {
+ if ({{Identifier.binderOptions}}?.{{Identifier.ErrorOnUnknownConfiguration}} is true)
+ {
+ {{MinimalDisplayString.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}}}'");
+ }
+ }
+
+ if ({{Identifier.temp}} is not null)
+ {
+ throw new InvalidOperationException($"{{exceptionMessage}}");
+ }
+ }
+ }
+ """);
+ }
+
private void EmitHasValueOrChildrenMethod()
{
_writer.WriteBlock($$"""
{
return true;
}
- return {{Identifier.HasChildren}}({{Identifier.configuration}});
+ return {{Identifier.AsConfigWithChildren}}({{Identifier.configuration}}) is not null;
}
""");
}
- private void EmitHasChildrenMethod()
+ private void EmitAsConfigWithChildrenMethod()
{
_writer.WriteBlock($$"""
- public static bool {{Identifier.HasChildren}}({{Identifier.IConfiguration}} {{Identifier.configuration}})
+ public static {{Identifier.IConfiguration}}? {{Identifier.AsConfigWithChildren}}({{Identifier.IConfiguration}} {{Identifier.configuration}})
{
- foreach ({{Identifier.IConfigurationSection}} {{Identifier.section}} in {{Identifier.configuration}}.{{Identifier.GetChildren}}())
+ foreach ({{Identifier.IConfigurationSection}} _ in {{Identifier.configuration}}.{{Identifier.GetChildren}}())
{
- return true;
+ return {{Identifier.configuration}};
}
- return false;
+ return null;
}
""");
}
numberStylesTypeDisplayString = "NumberStyles";
}
- string invariantCultureExpression = $"{cultureInfoTypeDisplayString}.InvariantCulture";
-
- string expressionForParsedValue;
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
string typeDisplayString = type.MinimalDisplayString;
+ string invariantCultureExpression = $"{cultureInfoTypeDisplayString}.InvariantCulture";
+
+ string parsedValueExpr;
switch (typeKind)
{
case StringParsableTypeKind.Enum:
{
- expressionForParsedValue = $"({typeDisplayString}){Identifier.Enum}.{Identifier.Parse}(typeof({typeDisplayString}), {Identifier.stringValue}, ignoreCase: true)";
+ parsedValueExpr = $"({typeDisplayString}){Identifier.Enum}.{Identifier.Parse}(typeof({typeDisplayString}), {Identifier.value}, ignoreCase: true)";
}
break;
case StringParsableTypeKind.ByteArray:
{
- expressionForParsedValue = $"Convert.FromBase64String({Identifier.stringValue})";
+ parsedValueExpr = $"Convert.FromBase64String({Identifier.value})";
}
break;
case StringParsableTypeKind.Integer:
{
- expressionForParsedValue = $"{typeDisplayString}.{Identifier.Parse}({Identifier.stringValue}, {numberStylesTypeDisplayString}.Integer, {invariantCultureExpression})";
+ parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {numberStylesTypeDisplayString}.Integer, {invariantCultureExpression})";
}
break;
case StringParsableTypeKind.Float:
{
- expressionForParsedValue = $"{typeDisplayString}.{Identifier.Parse}({Identifier.stringValue}, {numberStylesTypeDisplayString}.Float, {invariantCultureExpression})";
+ parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {numberStylesTypeDisplayString}.Float, {invariantCultureExpression})";
}
break;
case StringParsableTypeKind.Parse:
{
- expressionForParsedValue = $"{typeDisplayString}.{Identifier.Parse}({Identifier.stringValue})";
+ parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value})";
}
break;
case StringParsableTypeKind.ParseInvariant:
{
- expressionForParsedValue = $"{typeDisplayString}.{Identifier.Parse}({Identifier.stringValue}, {invariantCultureExpression})"; ;
+ parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {invariantCultureExpression})"; ;
}
break;
case StringParsableTypeKind.CultureInfo:
{
- expressionForParsedValue = $"{cultureInfoTypeDisplayString}.GetCultureInfo({Identifier.stringValue})";
+ parsedValueExpr = $"{cultureInfoTypeDisplayString}.GetCultureInfo({Identifier.value})";
}
break;
case StringParsableTypeKind.Uri:
{
- expressionForParsedValue = $"new Uri({Identifier.stringValue}, UriKind.RelativeOrAbsolute)";
+ parsedValueExpr = $"new Uri({Identifier.value}, UriKind.RelativeOrAbsolute)";
}
break;
default:
}
_writer.WriteBlock($$"""
- public static {{typeDisplayString}} {{type.ParseMethodName}}(string {{Identifier.stringValue}}, Func<string?> {{Identifier.getPath}})
+ public static {{typeDisplayString}} {{type.ParseMethodName}}(string {{Identifier.value}}, Func<string?> {{Identifier.getPath}})
{
try
{
- return {{expressionForParsedValue}};
+ return {{parsedValueExpr}};
""");
string exceptionArg1 = string.Format(ExceptionMessages.FailedBinding, $"{{{Identifier.getPath}()}}", $"{{typeof({typeDisplayString})}}");
""");
}
- private void EmitBindCoreImpl(TypeSpec type)
- {
- switch (type.SpecKind)
- {
- case TypeSpecKind.Enumerable:
- case TypeSpecKind.Dictionary:
- case TypeSpecKind.Object:
- {
- Debug.Assert(type.CanInitialize);
- EmitCheckForNullArgument_WithBlankLine_IfRequired(type.IsValueType);
- EmitBindCoreImplForComplexType(type);
- }
- break;
- case TypeSpecKind.Nullable:
- {
- EmitBindCoreImpl(((NullableSpec)type).UnderlyingType);
- }
- break;
- case TypeSpecKind.IConfigurationSection:
- {
- EmitCastToIConfigurationSection();
- _writer.WriteLine($"{Identifier.obj} = {Identifier.section};");
- }
- break;
- default:
- Debug.Fail("Invalid type kind", type.SpecKind.ToString());
- break;
- }
- }
-
- private void EmitBindCoreImplForComplexType(TypeSpec type)
- {
- if (type.InitializationStrategy is InitializationStrategy.Array)
- {
- EmitPopulationImplForArray((EnumerableSpec)type);
- }
- else if (type is EnumerableSpec enumerable)
- {
- EmitPopulationImplForEnumerableWithAdd(enumerable);
- }
- else if (type is DictionarySpec dictionary)
- {
- EmitBindCoreImplForDictionary(dictionary);
- }
- else
- {
- EmitBindCoreImplForObject((ObjectSpec)type);
- }
- }
-
private void EmitPopulationImplForArray(EnumerableSpec type)
{
EnumerableSpec concreteType = (EnumerableSpec)type.ConcreteType;
- // Create, bind, and add elements to temp list.
- string tempVarName = GetIncrementalVarName(Identifier.temp);
- EmitBindCoreCall(concreteType, tempVarName, Identifier.configuration, InitializationKind.Declaration);
+ // Create list and bind elements.
+ string tempIdentifier = GetIncrementalIdentifier(Identifier.temp);
+ EmitBindCoreCall(concreteType, tempIdentifier, Identifier.configuration, InitializationKind.Declaration);
- // Resize array and copy additional elements.
+ // Resize array and add binded elements.
_writer.WriteBlock($$"""
{{Identifier.Int32}} {{Identifier.originalCount}} = {{Identifier.obj}}.{{Identifier.Length}};
- {{Identifier.Array}}.{{Identifier.Resize}}(ref {{Identifier.obj}}, {{Identifier.originalCount}} + {{tempVarName}}.{{Identifier.Count}});
- {{tempVarName}}.{{Identifier.CopyTo}}({{Identifier.obj}}, {{Identifier.originalCount}});
+ {{Identifier.Array}}.{{Identifier.Resize}}(ref {{Identifier.obj}}, {{Identifier.originalCount}} + {{tempIdentifier}}.{{Identifier.Count}});
+ {{tempIdentifier}}.{{Identifier.CopyTo}}({{Identifier.obj}}, {{Identifier.originalCount}});
""");
}
{
EmitCollectionCastIfRequired(type, out string objIdentifier);
- _writer.WriteBlockStart($"foreach ({Identifier.IConfigurationSection} {Identifier.section} in {Identifier.configuration}.{Identifier.GetChildren}())");
+ Emit_Foreach_Section_In_ConfigChildren_BlockHeader();
TypeSpec elementType = type.ElementType;
stringParsableType,
Expression.sectionValue,
Expression.sectionPath,
- (parsedValueExpr) => _writer.WriteLine($"{objIdentifier}.{Identifier.Add}({parsedValueExpr}!);"),
- isCollectionElement: true);
+ (parsedValueExpr) => _writer.WriteLine($"{objIdentifier}.{Identifier.Add}({parsedValueExpr});"),
+ checkForNullSectionValue: true,
+ useIncrementalStringValueIdentifier: false);
}
else
{
- EmitBindCoreCall(elementType, Identifier.element, Identifier.section, InitializationKind.Declaration);
- _writer.WriteLine($"{objIdentifier}.{Identifier.Add}({Identifier.element});");
+ EmitBindCoreCall(elementType, Identifier.value, Identifier.section, InitializationKind.Declaration);
+ _writer.WriteLine($"{objIdentifier}.{Identifier.Add}({Identifier.value});");
}
_writer.WriteBlockEnd();
{
EmitCollectionCastIfRequired(type, out string objIdentifier);
- _writer.WriteBlockStart($"foreach ({Identifier.IConfigurationSection} {Identifier.section} in {Identifier.configuration}.{Identifier.GetChildren}())");
+ Emit_Foreach_Section_In_ConfigChildren_BlockHeader();
ParsableFromStringSpec keyType = type.KeyType;
TypeSpec elementType = type.ElementType;
// Parse key
EmitBindLogicFromString(
- keyType,
- Expression.sectionKey,
- Expression.sectionPath,
- Emit_BindAndAddLogic_ForElement);
+ keyType,
+ Expression.sectionKey,
+ Expression.sectionPath,
+ Emit_BindAndAddLogic_ForElement,
+ checkForNullSectionValue: false,
+ useIncrementalStringValueIdentifier: false);
void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
{
stringParsableElementType,
Expression.sectionValue,
Expression.sectionPath,
- (parsedValueExpr) => _writer.WriteLine($"{objIdentifier}[{parsedKeyExpr}!] = {parsedValueExpr}!;"),
- isCollectionElement: true);
+ writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{objIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"),
+ checkForNullSectionValue: true,
+ useIncrementalStringValueIdentifier: false);
}
else // For complex types:
{
Debug.Assert(elementType.CanInitialize);
- parsedKeyExpr += "!";
- if (keyType.StringParsableTypeKind is not StringParsableTypeKind.ConfigValue)
+ 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.WriteBlockStart($"if (!({conditionToUseExistingElement}))");
- EmitObjectInit(elementType, Identifier.element, InitializationKind.SimpleAssignment);
+ EmitObjectInit(elementType, Identifier.element, InitializationKind.SimpleAssignment, Identifier.section);
_writer.WriteBlockEnd();
if (elementType is CollectionSpec { InitializationStrategy: InitializationStrategy.ParameterizedConstructor or InitializationStrategy.ToEnumerableMethod } collectionSpec)
private void EmitBindCoreImplForObject(ObjectSpec type)
{
- if (type.Properties.Count == 0)
- {
- return;
- }
+ Debug.Assert(type.NeedsMemberBinding);
- string listOfStringDisplayName = "List<string>";
- _writer.WriteLine($"{listOfStringDisplayName}? {Identifier.temp} = null;");
-
- _writer.WriteBlockStart($"foreach ({Identifier.IConfigurationSection} {Identifier.section} in {Identifier.configuration}.{Identifier.GetChildren}())");
- _writer.WriteBlockStart($"switch ({Expression.sectionKey})");
+ string keyCacheFieldName = GetConfigKeyCacheFieldName(type);
+ string validateMethodCallExpr = $"{Identifier.ValidateConfigurationKeys}(typeof({type.MinimalDisplayString}), {keyCacheFieldName}, {Identifier.configuration}, {Identifier.binderOptions});";
+ _writer.WriteLine(validateMethodCallExpr);
foreach (PropertySpec property in type.Properties.Values)
{
- _writer.WriteLine($@"case ""{property.ConfigurationKeyName}"":");
- _writer.Indentation++;
- _writer.WriteBlockStart();
-
- bool success = true;
- if (property.ShouldBind())
+ bool noSetter_And_IsReadonly = !property.CanSet && property.Type is CollectionSpec { InitializationStrategy: InitializationStrategy.ParameterizedConstructor };
+ if (property.ShouldBind() && !noSetter_And_IsReadonly)
{
- success = EmitBindCoreImplForProperty(property, property.Type, parentType: type);
+ string containingTypeRef = property.IsStatic ? type.MinimalDisplayString : Identifier.obj;
+ EmitBindImplForMember(
+ property,
+ memberAccessExpr: $"{containingTypeRef}.{property.Name}",
+ GetSectionPathFromConfigurationExpression(property.ConfigurationKeyName),
+ canSet: property.CanSet);
}
+ }
+ }
- _writer.WriteBlockEnd();
+ private bool EmitBindImplForMember(
+ MemberSpec member,
+ string memberAccessExpr,
+ string sectionPathExpr,
+ bool canSet)
+ {
+ TypeSpec effectiveMemberType = member.Type.EffectiveType;
- if (success)
+ if (effectiveMemberType is ParsableFromStringSpec stringParsableType)
+ {
+ if (canSet)
{
- _writer.WriteLine("break;");
- }
+ bool checkForNullSectionValue = member is ParameterSpec
+ ? true
+ : stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue;
- _writer.Indentation--;
- }
-
- EmitSwitchDefault($$"""
- if ({{Identifier.binderOptions}}?.ErrorOnUnknownConfiguration == true)
- {
- ({{Identifier.temp}} ??= new {{listOfStringDisplayName}}()).Add($"'{{{Expression.sectionKey}}}'");
- }
- """);
+ string nullBangExpr = checkForNullSectionValue ? string.Empty : "!";
- // End switch on config child key.
- _writer.WriteBlockEnd();
+ EmitBlankLineIfRequired();
+ EmitBindLogicFromString(
+ stringParsableType,
+ $@"{Identifier.configuration}[""{member.ConfigurationKeyName}""]",
+ sectionPathExpr,
+ writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr}{nullBangExpr};"),
+ checkForNullSectionValue,
+ useIncrementalStringValueIdentifier: true);
+ }
- // End foreach on config.GetChildren().
- _writer.WriteBlockEnd();
+ return true;
+ }
- _writer.WriteBlankLine();
+ string sectionParseExpr = $"{GetSectionFromConfigurationExpression(member.ConfigurationKeyName)}";
- string exceptionMessage = string.Format(ExceptionMessages.MissingConfig, Identifier.ErrorOnUnknownConfiguration, Identifier.BinderOptions, $"{{typeof({type.MinimalDisplayString})}}", $@"{{string.Join("", "", {Identifier.temp})}}");
- _writer.WriteBlock($$"""
- if ({{Identifier.temp}} is not null)
- {
- throw new InvalidOperationException($"{{exceptionMessage}}");
- }
- """);
+ EmitBlankLineIfRequired();
- }
+ if (effectiveMemberType.SpecKind is TypeSpecKind.IConfigurationSection)
+ {
+ _writer.WriteLine($"{memberAccessExpr} = {sectionParseExpr};");
+ return true;
+ }
- private bool EmitBindCoreImplForProperty(PropertySpec property, TypeSpec propertyType, TypeSpec parentType)
- {
- string configurationKeyName = property.ConfigurationKeyName;
- string propertyParentReference = property.IsStatic ? parentType.MinimalDisplayString : Identifier.obj;
- string expressionForPropertyAccess = $"{propertyParentReference}.{property.Name}";
- string expressionForConfigValueIndexer = $@"{Identifier.configuration}[""{configurationKeyName}""]";
+ string sectionValidationCall = $"{Identifier.AsConfigWithChildren}({sectionParseExpr})";
+ string sectionIdentifier = GetIncrementalIdentifier(Identifier.section);
- bool canSet = property.CanSet;
+ _writer.WriteBlockStart($"if ({sectionValidationCall} is {Identifier.IConfigurationSection} {sectionIdentifier})");
- switch (propertyType.SpecKind)
+ bool success = !EmitInitException(effectiveMemberType);
+ if (success)
{
- case TypeSpecKind.ParsableFromString:
- {
- if (canSet && propertyType is ParsableFromStringSpec stringParsableType)
- {
- EmitBindLogicFromString(
- stringParsableType,
- expressionForConfigValueIndexer,
- Expression.sectionPath,
- (parsedValueExpr) => _writer.WriteLine($"{expressionForPropertyAccess} = {parsedValueExpr}!;"));
- }
- }
- break;
- case TypeSpecKind.IConfigurationSection:
- {
- _writer.WriteLine($"{expressionForPropertyAccess} = {Identifier.section};");
- }
- break;
- case TypeSpecKind.Nullable:
- {
- TypeSpec underlyingType = ((NullableSpec)propertyType).UnderlyingType;
- EmitBindCoreImplForProperty(property, underlyingType, parentType);
- }
- break;
- default:
- {
- if (EmitInitException(propertyType))
- {
- return false;
- }
-
- EmitBindCoreCallForProperty(property, propertyType, expressionForPropertyAccess);
- }
- break;
+ EmitBindCoreCallForMember(member, memberAccessExpr, sectionIdentifier, canSet);
}
- return true;
+ _writer.WriteBlockEnd();
+ return success;
}
- private void EmitBindCoreCallForProperty(PropertySpec property, TypeSpec effectivePropertyType, string expressionForPropertyAccess)
+ private void EmitBindCoreCallForMember(
+ MemberSpec member,
+ string memberAccessExpr,
+ string configArgExpr,
+ bool canSet)
{
- _writer.WriteBlockStart($"if ({Identifier.HasChildren}({Identifier.section}))");
- bool canGet = property.CanGet;
- bool canSet = property.CanSet;
- string effectivePropertyTypeDisplayString = effectivePropertyType.MinimalDisplayString;
+ TypeSpec memberType = member.Type;
+ TypeSpec effectiveMemberType = memberType.EffectiveType;
+ string effectiveMemberTypeDisplayString = effectiveMemberType.MinimalDisplayString;
+ bool canGet = member.CanGet;
- string tempVarName = GetIncrementalVarName(Identifier.temp);
- if (effectivePropertyType.IsValueType)
+ string tempIdentifier = GetIncrementalIdentifier(Identifier.temp);
+ InitializationKind initKind;
+ string targetObjAccessExpr;
+
+ if (effectiveMemberType.IsValueType)
{
- if (canSet)
+ if (!canSet)
{
- if (canGet)
- {
- TypeSpec actualPropertyType = property.Type;
- if (actualPropertyType.SpecKind is TypeSpecKind.Nullable)
- {
- string nullableTempVarName = GetIncrementalVarName(Identifier.temp);
+ return;
+ }
- _writer.WriteLine($"{actualPropertyType.MinimalDisplayString} {nullableTempVarName} = {expressionForPropertyAccess};");
+ Debug.Assert(canSet);
+ initKind = InitializationKind.None;
- _writer.WriteLine(
- $"{effectivePropertyTypeDisplayString} {tempVarName} = {nullableTempVarName}.{Identifier.HasValue} ? {nullableTempVarName}.{Identifier.Value} : new {effectivePropertyTypeDisplayString}();");
- }
- else
- {
- _writer.WriteLine($"{effectivePropertyTypeDisplayString} {tempVarName} = {expressionForPropertyAccess};");
- }
- }
- else
- {
- EmitObjectInit(effectivePropertyType, tempVarName, InitializationKind.Declaration);
- }
-
- _writer.WriteLine($@"{Identifier.BindCore}({Identifier.section}, ref {tempVarName}, {Identifier.binderOptions});");
- _writer.WriteLine($"{expressionForPropertyAccess} = {tempVarName};");
- }
- }
- else
- {
- if (canGet)
+ if (memberType.SpecKind is TypeSpecKind.Nullable)
{
- _writer.WriteLine($"{effectivePropertyTypeDisplayString} {tempVarName} = {expressionForPropertyAccess};");
- EmitObjectInit(effectivePropertyType, tempVarName, InitializationKind.AssignmentWithNullCheck);
- _writer.WriteLine($@"{Identifier.BindCore}({Identifier.section}, ref {tempVarName}, {Identifier.binderOptions});");
+ string nullableTempIdentifier = GetIncrementalIdentifier(Identifier.temp);
- if (canSet)
- {
- _writer.WriteLine($"{expressionForPropertyAccess} = {tempVarName};");
- }
+ _writer.WriteLine($"{memberType.MinimalDisplayString} {nullableTempIdentifier} = {memberAccessExpr};");
+
+ _writer.WriteLine(
+ $"{effectiveMemberTypeDisplayString} {tempIdentifier} = {nullableTempIdentifier}.{Identifier.HasValue} ? {nullableTempIdentifier}.{Identifier.Value} : new {effectiveMemberTypeDisplayString}();");
}
else
{
- Debug.Assert(canSet);
- EmitObjectInit(effectivePropertyType, tempVarName, InitializationKind.Declaration);
- _writer.WriteLine($@"{Identifier.BindCore}({Identifier.section}, ref {tempVarName}, {Identifier.binderOptions});");
- _writer.WriteLine($"{expressionForPropertyAccess} = {tempVarName};");
+ _writer.WriteLine($"{effectiveMemberTypeDisplayString} {tempIdentifier} = {memberAccessExpr};");
}
- }
- _writer.WriteBlockEnd();
+ targetObjAccessExpr = tempIdentifier;
+ }
+ else if (canGet)
+ {
+ targetObjAccessExpr = memberAccessExpr;
+ initKind = InitializationKind.AssignmentWithNullCheck;
+ }
+ else
+ {
+ targetObjAccessExpr = memberAccessExpr;
+ initKind = InitializationKind.SimpleAssignment;
+ }
+
+ Action<string>? writeOnSuccess = !canSet
+ ? null
+ : bindedValueIdentifier =>
+ {
+ if (memberAccessExpr != bindedValueIdentifier)
+ {
+ _writer.WriteLine($"{memberAccessExpr} = {bindedValueIdentifier};");
+ }
+ };
+
+ EmitBindCoreCall(
+ effectiveMemberType,
+ targetObjAccessExpr,
+ configArgExpr,
+ initKind,
+ writeOnSuccess);
}
private void EmitCollectionCastIfRequired(CollectionSpec type, out string objIdentifier)
}
}
- private void EmitSwitchDefault(string caseLogic, bool addBreak = true)
- {
- _writer.WriteLine("default:");
- _writer.Indentation++;
- _writer.WriteBlockStart();
- _writer.WriteBlock(caseLogic);
- _writer.WriteBlockEnd();
+ private void Emit_Foreach_Section_In_ConfigChildren_BlockHeader() =>
+ _writer.WriteBlockStart($"foreach ({Identifier.IConfigurationSection} {Identifier.section} in {Identifier.configuration}.{Identifier.GetChildren}())");
- if (addBreak)
- {
- _writer.WriteLine("break;");
- }
+ private static string GetSectionPathFromConfigurationExpression(string configurationKeyName)
+ => $@"{GetSectionFromConfigurationExpression(configurationKeyName)}.{Identifier.Path}";
- _writer.Indentation--;
+ private static string GetSectionFromConfigurationExpression(string configurationKeyName, bool addQuotes = true)
+ {
+ string argExpr = addQuotes ? $@"""{configurationKeyName}""" : configurationKeyName;
+ return $@"{Expression.configurationGetSection}({argExpr})";
}
+ private static string GetConfigKeyCacheFieldName(ObjectSpec type) =>
+ $"s_configKeys_{type.DisplayStringWithoutSpecialCharacters}";
+
private void Emit_NotSupportedException_TypeNotDetectedAsInput() =>
_writer.WriteLine(@$"throw new global::System.NotSupportedException($""{string.Format(ExceptionMessages.TypeNotDetectedAsInput, "{type}")}"");");
}
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Reflection;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
{
private sealed partial class Emitter
{
+ private static readonly AssemblyName s_assemblyName = typeof(Emitter).Assembly.GetName();
+
private enum InitializationKind
{
None = 0,
}
private static class Expression
{
+ public const string configurationGetSection = "configuration.GetSection";
public const string sectionKey = "section.Key";
public const string sectionPath = "section.Path";
public const string sectionValue = "section.Value";
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::{ConfigurationBindingGenerator.ProjectName}.{Identifier.CoreBindingHelper}";
+ 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";
private static class MinimalDisplayString
{
public const string NullableActionOfBinderOptions = "Action<BinderOptions>?";
+ public const string HashSetOfString = "HashSet<string>";
+ public const string LazyHashSetOfString = "Lazy<HashSet<string>>";
+ public const string ListOfString = "List<string>";
}
private static class Identifier
public const string optionsBuilder = nameof(optionsBuilder);
public const string originalCount = nameof(originalCount);
public const string section = nameof(section);
+ public const string sectionKey = nameof(sectionKey);
public const string services = nameof(services);
- public const string stringValue = nameof(stringValue);
public const string temp = nameof(temp);
public const string type = nameof(type);
+ public const string validateKeys = nameof(validateKeys);
+ public const string value = nameof(value);
public const string Add = nameof(Add);
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 BindCore = nameof(BindCore);
- public const string BindCoreUntyped = nameof(BindCoreUntyped);
public const string BinderOptions = nameof(BinderOptions);
public const string Configure = nameof(Configure);
public const string CopyTo = nameof(CopyTo);
public const string GeneratedServiceCollectionBinder = nameof(GeneratedServiceCollectionBinder);
public const string Get = nameof(Get);
public const string GetBinderOptions = nameof(GetBinderOptions);
- public const string GetCore = nameof(GetCore);
public const string GetChildren = nameof(GetChildren);
public const string GetSection = nameof(GetSection);
public const string GetValue = nameof(GetValue);
- public const string GetValueCore = nameof(GetValueCore);
- public const string HasChildren = nameof(HasChildren);
public const string HasConfig = nameof(HasConfig);
public const string HasValueOrChildren = nameof(HasValueOrChildren);
public const string HasValue = nameof(HasValue);
public const string TryGetValue = nameof(TryGetValue);
public const string TryParse = nameof(TryParse);
public const string Uri = nameof(Uri);
+ public const string ValidateConfigurationKeys = nameof(ValidateConfigurationKeys);
public const string Value = nameof(Value);
}
private void EmitBlankLineIfRequired()
{
- if (_precedingBlockExists)
+ if (_emitBlankLineBeforeNextStatement)
{
_writer.WriteBlankLine();
}
- _precedingBlockExists = true;
+ _emitBlankLineBeforeNextStatement = true;
}
private void EmitCheckForNullArgument_WithBlankLine_IfRequired(bool isValueType)
return false;
}
+ private void EmitRootBindingClassBlockStart(string className)
+ {
+ EmitBlankLineIfRequired();
+ _writer.WriteBlock($$"""
+ /// <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 GetIncrementalVarName(string prefix) => $"{prefix}{_parseValueCount++}";
+ 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;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Microsoft.CodeAnalysis;
-
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
public sealed partial class ConfigurationBindingGenerator
return;
}
- EmitBlankLineIfRequired();
- _writer.WriteLine("/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>");
- _writer.WriteBlockStart($"internal static class {Identifier.GeneratedOptionsBuilderBinder}");
- _precedingBlockExists = false;
+ EmitRootBindingClassBlockStart(Identifier.GeneratedOptionsBuilderBinder);
EmitBindMethods_Extensions_OptionsBuilder();
EmitBindConfigurationMethod();
EmitMethodBlockStart("Bind", paramList, documentation);
_writer.WriteLine($"return global::{Identifier.GeneratedOptionsBuilderBinder}.Bind({Identifier.optionsBuilder}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
_writer.WriteBlockEnd();
- _writer.WriteBlankLine();
}
EmitMethodBlockStart(
_writer.WriteBlock($$"""
{{FullyQualifiedDisplayString.IConfiguration}} {{Identifier.section}} = string.Equals(string.Empty, {{Identifier.configSectionPath}}, global::System.StringComparison.OrdinalIgnoreCase) ? {{Identifier.configuration}} : {{Identifier.configuration}}.{{Identifier.GetSection}}({{Identifier.configSectionPath}});
- {{FullyQualifiedDisplayString.CoreBindingHelper}}.{{Identifier.BindCoreUntyped}}({{Identifier.section}}, {{Identifier.obj}}, typeof({{Identifier.TOptions}}), {{Identifier.configureOptions}});
+ {{FullyQualifiedDisplayString.CoreBindingHelper}}.{{nameof(MethodsToGen_CoreBindingHelper.BindCoreUntyped)}}({{Identifier.section}}, {{Identifier.obj}}, typeof({{Identifier.TOptions}}), {{Identifier.configureOptions}});
""");
_writer.WriteBlockEnd(");");
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Microsoft.CodeAnalysis;
-
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
public sealed partial class ConfigurationBindingGenerator
return;
}
- EmitBlankLineIfRequired();
-
- _writer.WriteLine("/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>");
- _writer.WriteBlockStart($"internal static class {Identifier.GeneratedServiceCollectionBinder}");
- _precedingBlockExists = false;
+ EmitRootBindingClassBlockStart(Identifier.GeneratedServiceCollectionBinder);
const string defaultNameExpr = "string.Empty";
const string configureMethodString = $"global::{Identifier.GeneratedServiceCollectionBinder}.{Identifier.Configure}";
}
string optionsNamespaceName = "global::Microsoft.Extensions.Options";
- string bindCoreUntypedDisplayString = GetHelperMethodDisplayString(Identifier.BindCoreUntyped);
+ string bindCoreUntypedDisplayString = GetHelperMethodDisplayString(nameof(MethodsToGen_CoreBindingHelper.BindCoreUntyped));
EmitBlockStart(paramList: $"string? {Identifier.name}, " + configParam + $", {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}");
""");
_writer.WriteBlockEnd();
- _precedingBlockExists = true;
+ _emitBlankLineBeforeNextStatement = true;
}
private void EmitBlockStart(string paramList)
GetCore = 0x4,
GetValueCore = 0x8,
Initialize = 0x10,
+ AsConfigWithChildren = 0x20,
}
/// <summary>
_sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
typeSpecs.Add(typeSpec);
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, typeSpec);
}
static ITypeSymbol? ResolveType(IOperation conversionOperation) =>
IMethodReferenceOperation m when m.Method.MethodKind == MethodKind.Constructor => m.Method.ContainingType,
IMethodReferenceOperation m => m.Method.ReturnType,
IAnonymousFunctionOperation f => f.Symbol.ReturnType,
+ IParameterReferenceOperation p => p.Parameter.Type,
_ => null
};
}
private static readonly char[] s_newLine = Environment.NewLine.ToCharArray();
private int _indentation;
-
- public int Indentation
- {
- get => _indentation;
- set
- {
- if (value < 0)
- {
- Throw();
- static void Throw() => throw new ArgumentOutOfRangeException(nameof(value));
- }
-
- _indentation = value;
- }
- }
-
public void WriteBlockStart(string? declaration = null)
{
if (declaration is not null)
WriteLine(declaration);
}
WriteLine("{");
- Indentation++;
+ _indentation++;
}
public void WriteBlockEnd(string? extra = null)
{
- Indentation--;
- Debug.Assert(Indentation > -1);
+ _indentation--;
+ Debug.Assert(_indentation > -1);
WriteLine($"}}{extra}");
}
public void WriteLine(string source)
{
- _sb.Append(' ', 4 * Indentation);
+ _sb.Append(' ', 4 * _indentation);
_sb.AppendLine(source);
}
public SourceText ToSourceText()
{
- Debug.Assert(Indentation == 0 && _sb.Length > 0);
+ Debug.Assert(_indentation == 0 && _sb.Length > 0);
return SourceText.From(_sb.ToString(), Encoding.UTF8);
}
private unsafe void WriteLine(ReadOnlySpan<char> source)
{
- _sb.Append(' ', 4 * Indentation);
+ _sb.Append(' ', 4 * _indentation);
fixed (char* ptr = source)
{
_sb.Append(ptr, source.Length);
<Compile Include="Model\ConfigurationSectionSpec.cs" />
<Compile Include="Model\InitializationStrategy.cs" />
<Compile Include="Model\KnownTypeSymbols.cs" />
+ <Compile Include="Model\MemberSpec.cs" />
<Compile Include="Model\NullableSpec.cs" />
<Compile Include="Model\ObjectSpec.cs" />
<Compile Include="Model\ParameterSpec.cs" />
public required CollectionPopulationStrategy PopulationStrategy { get; init; }
- public override bool CanInitialize => ConcreteType?.CanInitialize ?? CanInitCompexType;
+ public override bool CanInitialize => ConcreteType?.CanInitialize ?? CanInitComplexObject();
public override required InitializationStrategy InitializationStrategy { get; set; }
public required string? ToEnumerableMethodCall { get; init; }
+
+ public sealed override bool NeedsMemberBinding => true;
}
internal sealed record EnumerableSpec : CollectionSpec
--- /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.Diagnostics;
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
+{
+ internal abstract record MemberSpec
+ {
+ public MemberSpec(ISymbol member)
+ {
+ Debug.Assert(member is IPropertySymbol or IParameterSymbol);
+ Name = member.Name;
+ DefaultValueExpr = "default";
+ }
+
+ public string Name { get; }
+ public bool ErrorOnFailedBinding { get; protected set; }
+ public string DefaultValueExpr { get; protected set; }
+
+ public required TypeSpec Type { get; init; }
+ public required string ConfigurationKeyName { get; init; }
+
+ public abstract bool CanGet { get; }
+ public abstract bool CanSet { get; }
+ }
+}
// 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 Microsoft.CodeAnalysis;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
internal sealed record NullableSpec : TypeSpec
{
- public NullableSpec(ITypeSymbol type) : base(type) { }
+ private readonly TypeSpec _underlyingType;
- public override TypeSpecKind SpecKind => TypeSpecKind.Nullable;
-
- public required TypeSpec UnderlyingType { get; init; }
-
- public override string? InitExceptionMessage
+ public NullableSpec(ITypeSymbol type, TypeSpec underlyingType) : base(type)
{
- get => UnderlyingType.InitExceptionMessage;
- set => throw new InvalidOperationException();
+ _underlyingType = underlyingType;
}
+
+ public override TypeSpecKind SpecKind => TypeSpecKind.Nullable;
+
+ public override TypeSpec EffectiveType => _underlyingType;
}
}
using System;
using System.Collections.Generic;
+using System.Linq;
using Microsoft.CodeAnalysis;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
internal sealed record ObjectSpec : TypeSpec
{
- public ObjectSpec(INamedTypeSymbol type) : base(type)
- {
- InitializeMethodDisplayString = $"Initialize{type.Name.Replace(".", string.Empty).Replace("<", string.Empty).Replace(">", string.Empty)}";
- }
+ public ObjectSpec(INamedTypeSymbol type) : base(type) { }
public override TypeSpecKind SpecKind => TypeSpecKind.Object;
public override InitializationStrategy InitializationStrategy { get; set; }
- public override bool CanInitialize => CanInitCompexType;
+ public override bool CanInitialize => CanInitComplexObject();
public Dictionary<string, PropertySpec> Properties { get; } = new(StringComparer.OrdinalIgnoreCase);
public List<ParameterSpec> ConstructorParameters { get; } = new();
- public string? InitializeMethodDisplayString { get; }
+ 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());
}
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
- internal sealed record ParameterSpec
+ internal sealed record ParameterSpec : MemberSpec
{
- public ParameterSpec(IParameterSymbol parameter)
+ public ParameterSpec(IParameterSymbol parameter) : base(parameter)
{
- Name = parameter.Name;
RefKind = parameter.RefKind;
- HasExplicitDefaultValue = parameter.HasExplicitDefaultValue;
- if (HasExplicitDefaultValue)
+ if (parameter.HasExplicitDefaultValue)
{
string formatted = SymbolDisplay.FormatPrimitive(parameter.ExplicitDefaultValue, quoteStrings: true, useHexadecimalNumbers: false);
- DefaultValue = formatted is "null" ? "default!" : formatted;
+ if (formatted is not "null")
+ {
+ DefaultValueExpr = formatted;
+ }
+ }
+ else
+ {
+ ErrorOnFailedBinding = true;
}
}
- public required TypeSpec Type { get; init; }
-
- public string Name { get; }
-
- public required string ConfigurationKeyName { get; init; }
-
public RefKind RefKind { get; }
- public bool HasExplicitDefaultValue { get; init; }
+ public override bool CanGet => false;
- public string DefaultValue { get; } = "default!";
+ public override bool CanSet => true;
}
}
{
get
{
- Debug.Assert(StringParsableTypeKind is not StringParsableTypeKind.ConfigValue);
+ Debug.Assert(StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue);
_parseMethodName ??= StringParsableTypeKind is StringParsableTypeKind.ByteArray
? "ParseByteArray"
internal enum StringParsableTypeKind
{
None = 0,
- ConfigValue = 1,
+
+ /// <summary>
+ /// Declared types that can be assigned directly from IConfigurationSection.Value, i.e. string and tyepof(object).
+ /// </summary>
+ AssignFromSectionValue = 1,
Enum = 2,
ByteArray = 3,
Integer = 4,
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
- internal sealed record PropertySpec
+ internal sealed record PropertySpec : MemberSpec
{
- public PropertySpec(IPropertySymbol property)
+ public PropertySpec(IPropertySymbol property) : base(property)
{
- Name = property.Name;
- IsStatic = property.IsStatic;
+ IMethodSymbol? setMethod = property.SetMethod;
+ bool setterIsPublic = setMethod?.DeclaredAccessibility is Accessibility.Public;
+ bool isInitOnly = setMethod?.IsInitOnly is true;
- bool setterIsPublic = property.SetMethod?.DeclaredAccessibility is Accessibility.Public;
- IsInitOnly = property.SetMethod?.IsInitOnly == true;
- IsRequired = property.IsRequired;
- SetOnInit = setterIsPublic && (IsInitOnly || IsRequired);
- CanSet = setterIsPublic && !IsInitOnly;
+ IsStatic = property.IsStatic;
+ SetOnInit = setterIsPublic && (property.IsRequired || isInitOnly);
+ CanSet = setterIsPublic && !isInitOnly;
CanGet = property.GetMethod?.DeclaredAccessibility is Accessibility.Public;
}
- public required TypeSpec Type { get; init; }
-
public ParameterSpec? MatchingCtorParam { get; set; }
- public string Name { get; }
-
public bool IsStatic { get; }
- public bool IsRequired { get; }
-
- public bool IsInitOnly { get; }
-
public bool SetOnInit { get; }
- public bool CanGet { get; }
-
- public bool CanSet { get; }
+ public override bool CanGet { get; }
- public required string ConfigurationKeyName { get; init; }
+ public override bool CanSet { get; }
- public bool ShouldBind() =>
- (CanGet || CanSet) &&
- !(!CanSet && (Type as CollectionSpec)?.InitializationStrategy is InitializationStrategy.ParameterizedConstructor);
+ public bool ShouldBind() => CanGet || CanSet;
}
}
public Dictionary<MethodsToGen_ConfigurationBinder, HashSet<TypeSpec>> TypesForGen_ConfigurationBinder_BindMethods { get; } = new();
public HashSet<ParsableFromStringSpec> PrimitivesForHelperGen { get; } = new();
- public HashSet<string> TypeNamespaces { get; } = new() { "Microsoft.Extensions.Configuration", "System.Globalization" };
+ public HashSet<string> TypeNamespaces { get; } = new()
+ {
+ "System",
+ "System.CodeDom.Compiler",
+ "System.Globalization",
+ "Microsoft.Extensions.Configuration",
+ };
public MethodsToGen_CoreBindingHelper MethodsToGen_CoreBindingHelper { get; set; }
public MethodsToGen_ConfigurationBinder MethodsToGen_ConfigurationBinder { get; set; }
public MethodsToGen_Extensions_OptionsBuilder MethodsToGen_OptionsBuilderExt { get; set; }
public MethodsToGen_Extensions_ServiceCollection MethodsToGen_ServiceCollectionExt { get; set; }
-
- public bool ShouldEmitHasChildren { get; set; }
}
}
FullyQualifiedDisplayString = type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
MinimalDisplayString = type.ToDisplayString(s_minimalDisplayFormat);
Name = Namespace + "." + MinimalDisplayString.Replace(".", "+");
+ IsInterface = type.TypeKind is TypeKind.Interface;
}
public string Name { get; }
public virtual bool CanInitialize => true;
- /// <summary>
- /// Location in the input compilation we picked up a call to Bind, Get, or Configure.
- /// </summary>
- public required Location? Location { get; init; }
+ public virtual bool NeedsMemberBinding { get; }
- protected bool CanInitCompexType => InitializationStrategy is not InitializationStrategy.None && InitExceptionMessage is null;
+ public virtual TypeSpec EffectiveType => this;
+
+ public bool IsInterface { get; }
+
+ protected bool CanInitComplexObject() => InitializationStrategy is not InitializationStrategy.None && InitExceptionMessage is null;
}
internal enum TypeSpecKind
#endif
.Configuration.Binder.Tests
{
- public partial class ConfigurationBinderCollectionTests
+ public sealed partial class ConfigurationBinderCollectionTests : ConfigurationBinderTestsBase
{
[Fact]
public void GetList()
public T Value { get; set; }
}
+ public record GenericOptionsRecord<T>(T Value);
+
+ public class GenericOptionsWithParamCtor<T>
+ {
+ public GenericOptionsWithParamCtor(T value) => Value = value;
+
+ public T Value { get; }
+ }
+
public class OptionsWithNesting
{
public NestedOptions Nested { get; set; }
#endif
.Configuration.Binder.Tests
{
- public partial class ConfigurationBinderTests
+ public abstract class ConfigurationBinderTestsBase
+ {
+ public ConfigurationBinderTestsBase()
+ {
+#if LAUNCH_DEBUGGER
+if (!System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Launch(); }
+#endif
+ }
+ }
+
+ public sealed partial class ConfigurationBinderTests : ConfigurationBinderTestsBase
{
[Fact]
public void BindWithNestedTypesWithReadOnlyProperties()
Assert.Equal(0, obj.Int32);
Assert.False(obj.Boolean);
}
+
+ [Fact]
+ public void AllowsCaseInsensitiveMatch()
+ {
+ var configuration = TestHelpers.GetConfigurationFromJsonString("""
+ {
+ "vaLue": "MyString",
+ }
+ """);
+
+ GenericOptions<string> obj = new();
+ configuration.Bind(obj);
+ Assert.Equal("MyString", obj.Value);
+
+ GenericOptionsRecord<string> obj1 = configuration.Get<GenericOptionsRecord<string>>();
+ Assert.Equal("MyString", obj1.Value);
+
+ GenericOptionsWithParamCtor<string> obj2 = configuration.Get<GenericOptionsWithParamCtor<string>>();
+ Assert.Equal("MyString", obj2.Value);
+ }
}
}
// <auto-generated/>
#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
{
/// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue2)
+ if (section.Value is string value)
{
- obj[section.Key!] = ParseInt(stringValue2, () => section.Path)!;
+ obj[section.Key] = ParseInt(value, () => section.Path);
}
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue3)
+ if (section.Value is string value)
{
- obj.Add(stringValue3!);
+ obj.Add(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)
+ {
+ obj.Add(ParseInt(value, () => section.Path));
+ }
+ }
+ }
+
+ 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)
+ {
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue4)
+ if (section.Value is string value)
+ {
+ temp.Add(ParseInt(value, () => section.Path));
+ }
+ }
+ }
+
+ 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)
{
- temp.Add(ParseInt(stringValue4, () => section.Path)!);
+ obj[section.Key] = ParseInt(value, () => section.Path);
+ }
+ }
+ }
+
+ 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)
+ {
+ obj[section.Key] = ParseInt(value, () => section.Path);
}
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue6)
+ if (section.Value is string value)
{
- temp[section.Key!] = ParseInt(stringValue6, () => section.Path)!;
+ temp[section.Key] = ParseInt(value, () => section.Path);
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClassWithCustomCollections), s_configKeys_ProgramMyClassWithCustomCollections, configuration, binderOptions);
+
+ if (AsConfigWithChildren(configuration.GetSection("CustomDictionary")) is IConfigurationSection section1)
{
- switch (section.Key)
- {
- case "CustomDictionary":
- {
- if (HasChildren(section))
- {
- Program.CustomDictionary<string, int> temp7 = obj.CustomDictionary;
- temp7 ??= new Program.CustomDictionary<string, int>();
- BindCore(section, ref temp7, binderOptions);
- obj.CustomDictionary = temp7;
- }
- }
- break;
- case "CustomList":
- {
- if (HasChildren(section))
- {
- Program.CustomList temp8 = obj.CustomList;
- temp8 ??= new Program.CustomList();
- BindCore(section, ref temp8, binderOptions);
- obj.CustomList = temp8;
- }
- }
- break;
- case "IReadOnlyList":
- {
- if (HasChildren(section))
- {
- IReadOnlyList<int> temp9 = obj.IReadOnlyList;
- temp9 = temp9 is null ? new List<int>() : new List<int>(temp9);
- BindCore(section, ref temp9, binderOptions);
- obj.IReadOnlyList = temp9;
- }
- }
- break;
- case "IReadOnlyDictionary":
- {
- if (HasChildren(section))
- {
- IReadOnlyDictionary<string, int> temp10 = obj.IReadOnlyDictionary;
- temp10 = temp10 is null ? new Dictionary<string, int>() : temp10.ToDictionary(pair => pair.Key, pair => pair.Value);
- BindCore(section, ref temp10, binderOptions);
- obj.IReadOnlyDictionary = temp10;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ Program.CustomDictionary<string, int> temp3 = obj.CustomDictionary;
+ temp3 ??= new Program.CustomDictionary<string, int>();
+ BindCore(section1, ref temp3, binderOptions);
+ obj.CustomDictionary = temp3;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("CustomList")) is IConfigurationSection section4)
+ {
+ Program.CustomList temp6 = obj.CustomList;
+ temp6 ??= new Program.CustomList();
+ BindCore(section4, ref temp6, binderOptions);
+ obj.CustomList = temp6;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("IReadOnlyList")) is IConfigurationSection section7)
+ {
+ IReadOnlyList<int> temp9 = obj.IReadOnlyList;
+ temp9 = temp9 is null ? new List<int>() : new List<int>(temp9);
+ BindCore(section7, ref temp9, binderOptions);
+ obj.IReadOnlyList = temp9;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("IReadOnlyDictionary")) is IConfigurationSection section10)
+ {
+ IReadOnlyDictionary<string, int> temp12 = obj.IReadOnlyDictionary;
+ temp12 = temp12 is null ? new Dictionary<string, int>() : temp12.ToDictionary(pair => pair.Key, pair => pair.Value);
+ BindCore(section10, ref temp12, binderOptions);
+ obj.IReadOnlyDictionary = temp12;
}
+ }
- if (temp is not null)
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClassWithCustomCollections)}: {string.Join(", ", temp)}");
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (obj is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue0)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue0, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue2)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue2!;
+ obj[section.Key] = value;
}
}
}
- public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
- {
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
- }
-
public static void BindCore(IConfiguration configuration, ref Dictionary<string, Program.MyClass2> obj, BinderOptions? binderOptions)
{
if (obj is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (!(obj.TryGetValue(section.Key!, out Program.MyClass2? element) && element is not null))
+ if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
{
element = new Program.MyClass2();
}
- BindCore(section, ref element!, binderOptions);
- obj[section.Key!] = element;
+ obj[section.Key] = element;
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value1)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue6)
- {
- obj.MyInt = ParseInt(stringValue6, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp7 = obj.MyList;
- temp7 ??= new List<int>();
- BindCore(section, ref temp7, binderOptions);
- obj.MyList = temp7;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp8 = obj.MyDictionary;
- temp8 ??= new Dictionary<string, string>();
- BindCore(section, ref temp8, binderOptions);
- obj.MyDictionary = temp8;
- }
- }
- break;
- case "MyComplexDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, Program.MyClass2> temp9 = obj.MyComplexDictionary;
- temp9 ??= new Dictionary<string, Program.MyClass2>();
- BindCore(section, ref temp9, binderOptions);
- obj.MyComplexDictionary = temp9;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section2)
+ {
+ List<int> temp4 = obj.MyList;
+ temp4 ??= new List<int>();
+ BindCore(section2, ref temp4, binderOptions);
+ obj.MyList = temp4;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section5)
+ {
+ Dictionary<string, string> temp7 = obj.MyDictionary;
+ temp7 ??= new Dictionary<string, string>();
+ BindCore(section5, ref temp7, binderOptions);
+ obj.MyDictionary = temp7;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyComplexDictionary")) is IConfigurationSection section8)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ Dictionary<string, Program.MyClass2> temp10 = obj.MyComplexDictionary;
+ temp10 ??= new Dictionary<string, Program.MyClass2>();
+ BindCore(section8, ref temp10, binderOptions);
+ obj.MyComplexDictionary = temp10;
}
}
- public static bool HasChildren(IConfiguration configuration)
+ /// <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)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
+ }
+ }
+
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
+ {
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
-// <auto-generated/>
+// <auto-generated/>
#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
{
/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (obj is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue0)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue0, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue2)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue2!;
+ obj[section.Key] = value;
}
}
}
- public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
- {
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
- }
-
public static void BindCore(IConfiguration configuration, ref Dictionary<string, Program.MyClass2> obj, BinderOptions? binderOptions)
{
if (obj is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (!(obj.TryGetValue(section.Key!, out Program.MyClass2? element) && element is not null))
+ if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
{
element = new Program.MyClass2();
}
- BindCore(section, ref element!, binderOptions);
- obj[section.Key!] = element;
+ obj[section.Key] = element;
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value1)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue6)
- {
- obj.MyInt = ParseInt(stringValue6, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp7 = obj.MyList;
- temp7 ??= new List<int>();
- BindCore(section, ref temp7, binderOptions);
- obj.MyList = temp7;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp8 = obj.MyDictionary;
- temp8 ??= new Dictionary<string, string>();
- BindCore(section, ref temp8, binderOptions);
- obj.MyDictionary = temp8;
- }
- }
- break;
- case "MyComplexDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, Program.MyClass2> temp9 = obj.MyComplexDictionary;
- temp9 ??= new Dictionary<string, Program.MyClass2>();
- BindCore(section, ref temp9, binderOptions);
- obj.MyComplexDictionary = temp9;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section2)
+ {
+ List<int> temp4 = obj.MyList;
+ temp4 ??= new List<int>();
+ BindCore(section2, ref temp4, binderOptions);
+ obj.MyList = temp4;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section5)
+ {
+ Dictionary<string, string> temp7 = obj.MyDictionary;
+ temp7 ??= new Dictionary<string, string>();
+ BindCore(section5, ref temp7, binderOptions);
+ obj.MyDictionary = temp7;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyComplexDictionary")) is IConfigurationSection section8)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ Dictionary<string, Program.MyClass2> temp10 = obj.MyComplexDictionary;
+ temp10 ??= new Dictionary<string, Program.MyClass2>();
+ BindCore(section8, ref temp10, binderOptions);
+ obj.MyComplexDictionary = temp10;
}
}
- public static bool HasChildren(IConfiguration configuration)
+ /// <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)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
+ }
+ }
+
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
+ {
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
-// <auto-generated/>
+// <auto-generated/>
#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
{
/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (obj is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue0)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue0, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue2)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue2!;
+ obj[section.Key] = value;
}
}
}
- public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
- {
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
- }
-
public static void BindCore(IConfiguration configuration, ref Dictionary<string, Program.MyClass2> obj, BinderOptions? binderOptions)
{
if (obj is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (!(obj.TryGetValue(section.Key!, out Program.MyClass2? element) && element is not null))
+ if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
{
element = new Program.MyClass2();
}
- BindCore(section, ref element!, binderOptions);
- obj[section.Key!] = element;
+ obj[section.Key] = element;
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value1)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue6)
- {
- obj.MyInt = ParseInt(stringValue6, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp7 = obj.MyList;
- temp7 ??= new List<int>();
- BindCore(section, ref temp7, binderOptions);
- obj.MyList = temp7;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp8 = obj.MyDictionary;
- temp8 ??= new Dictionary<string, string>();
- BindCore(section, ref temp8, binderOptions);
- obj.MyDictionary = temp8;
- }
- }
- break;
- case "MyComplexDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, Program.MyClass2> temp9 = obj.MyComplexDictionary;
- temp9 ??= new Dictionary<string, Program.MyClass2>();
- BindCore(section, ref temp9, binderOptions);
- obj.MyComplexDictionary = temp9;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section2)
+ {
+ List<int> temp4 = obj.MyList;
+ temp4 ??= new List<int>();
+ BindCore(section2, ref temp4, binderOptions);
+ obj.MyList = temp4;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section5)
+ {
+ Dictionary<string, string> temp7 = obj.MyDictionary;
+ temp7 ??= new Dictionary<string, string>();
+ BindCore(section5, ref temp7, binderOptions);
+ obj.MyDictionary = temp7;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyComplexDictionary")) is IConfigurationSection section8)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ Dictionary<string, Program.MyClass2> temp10 = obj.MyComplexDictionary;
+ temp10 ??= new Dictionary<string, Program.MyClass2>();
+ BindCore(section8, ref temp10, binderOptions);
+ obj.MyComplexDictionary = temp10;
}
}
- public static bool HasChildren(IConfiguration configuration)
+ /// <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)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
+ }
+ }
+
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
+ {
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
-// <auto-generated/>
+// <auto-generated/>
#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
{
/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (obj is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue0)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue0, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue2)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue2!;
+ obj[section.Key] = value;
}
}
}
- public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
- {
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
- }
-
public static void BindCore(IConfiguration configuration, ref Dictionary<string, Program.MyClass2> obj, BinderOptions? binderOptions)
{
if (obj is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (!(obj.TryGetValue(section.Key!, out Program.MyClass2? element) && element is not null))
+ if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
{
element = new Program.MyClass2();
}
- BindCore(section, ref element!, binderOptions);
- obj[section.Key!] = element;
+ obj[section.Key] = element;
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value1)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue6)
- {
- obj.MyInt = ParseInt(stringValue6, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp7 = obj.MyList;
- temp7 ??= new List<int>();
- BindCore(section, ref temp7, binderOptions);
- obj.MyList = temp7;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp8 = obj.MyDictionary;
- temp8 ??= new Dictionary<string, string>();
- BindCore(section, ref temp8, binderOptions);
- obj.MyDictionary = temp8;
- }
- }
- break;
- case "MyComplexDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, Program.MyClass2> temp9 = obj.MyComplexDictionary;
- temp9 ??= new Dictionary<string, Program.MyClass2>();
- BindCore(section, ref temp9, binderOptions);
- obj.MyComplexDictionary = temp9;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section2)
+ {
+ List<int> temp4 = obj.MyList;
+ temp4 ??= new List<int>();
+ BindCore(section2, ref temp4, binderOptions);
+ obj.MyList = temp4;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section5)
+ {
+ Dictionary<string, string> temp7 = obj.MyDictionary;
+ temp7 ??= new Dictionary<string, string>();
+ BindCore(section5, ref temp7, binderOptions);
+ obj.MyDictionary = temp7;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyComplexDictionary")) is IConfigurationSection section8)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ Dictionary<string, Program.MyClass2> temp10 = obj.MyComplexDictionary;
+ temp10 ??= new Dictionary<string, Program.MyClass2>();
+ BindCore(section8, ref temp10, binderOptions);
+ obj.MyComplexDictionary = temp10;
}
}
- public static bool HasChildren(IConfiguration configuration)
+ /// <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)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
+ }
+ }
+
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
+ {
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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" });
+
public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue2)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue2, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- var temp3 = new List<int>();
- BindCore(configuration, ref temp3, binderOptions);
+ var temp2 = new List<int>();
+ BindCore(configuration, ref temp2, binderOptions);
int originalCount = obj.Length;
- Array.Resize(ref obj, originalCount + temp3.Count);
- temp3.CopyTo(obj, originalCount);
+ Array.Resize(ref obj, originalCount + temp2.Count);
+ temp2.CopyTo(obj, originalCount);
}
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue6)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue6!;
+ obj[section.Key] = value;
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value5)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue8)
- {
- obj.MyInt = ParseInt(stringValue8, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp9 = obj.MyList;
- temp9 ??= new List<int>();
- BindCore(section, ref temp9, binderOptions);
- obj.MyList = temp9;
- }
- }
- break;
- case "MyArray":
- {
- if (HasChildren(section))
- {
- int[] temp10 = obj.MyArray;
- temp10 ??= new int[0];
- BindCore(section, ref temp10, binderOptions);
- obj.MyArray = temp10;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp11 = obj.MyDictionary;
- temp11 ??= new Dictionary<string, string>();
- BindCore(section, ref temp11, binderOptions);
- obj.MyDictionary = temp11;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value5, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section6)
+ {
+ List<int> temp8 = obj.MyList;
+ temp8 ??= new List<int>();
+ BindCore(section6, ref temp8, binderOptions);
+ obj.MyList = temp8;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyArray")) is IConfigurationSection section9)
+ {
+ int[] temp11 = obj.MyArray;
+ temp11 ??= new int[0];
+ BindCore(section9, ref temp11, binderOptions);
+ obj.MyArray = temp11;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section12)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ Dictionary<string, string> temp14 = obj.MyDictionary;
+ temp14 ??= new Dictionary<string, string>();
+ BindCore(section12, ref temp14, binderOptions);
+ obj.MyDictionary = temp14;
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
+
+ if (configuration["MyInt"] is string value15)
{
- switch (section.Key)
- {
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue12)
- {
- obj.MyInt = ParseInt(stringValue12, () => section.Path)!;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value15, () => configuration.GetSection("MyInt").Path);
}
+ }
- if (temp is not null)
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass2)}: {string.Join(", ", temp)}");
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
IConfigurationSection section = configuration.GetSection(key);
+ if (section.Value is not string value)
+ {
+ return null;
+ }
+
if (type == typeof(int))
{
- if (section.Value is string stringValue0)
- {
- return ParseInt(stringValue0, () => section.Path);
- }
+ return ParseInt(value, () => section.Path);
}
if (type == typeof(bool?))
{
- if (section.Value is string stringValue1)
- {
- return ParseBool(stringValue1, () => section.Path);
- }
+ return ParseBool(value, () => section.Path);
}
if (type == typeof(byte[]))
{
- if (section.Value is string stringValue2)
- {
- return ParseByteArray(stringValue2, () => section.Path);
- }
+ return ParseByteArray(value, () => section.Path);
}
if (type == typeof(CultureInfo))
{
- if (section.Value is string stringValue3)
- {
- return ParseCultureInfo(stringValue3, () => section.Path);
- }
+ return ParseCultureInfo(value, () => section.Path);
}
return null;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static bool ParseBool(string stringValue, Func<string?> getPath)
+ public static bool ParseBool(string value, Func<string?> getPath)
{
try
{
- return bool.Parse(stringValue);
+ return bool.Parse(value);
}
catch (Exception exception)
{
}
}
- public static byte[] ParseByteArray(string stringValue, Func<string?> getPath)
+ public static byte[] ParseByteArray(string value, Func<string?> getPath)
{
try
{
- return Convert.FromBase64String(stringValue);
+ return Convert.FromBase64String(value);
}
catch (Exception exception)
{
}
}
- public static CultureInfo ParseCultureInfo(string stringValue, Func<string?> getPath)
+ public static CultureInfo ParseCultureInfo(string value, Func<string?> getPath)
{
try
{
- return CultureInfo.GetCultureInfo(stringValue);
+ return CultureInfo.GetCultureInfo(value);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
IConfigurationSection section = configuration.GetSection(key);
+ if (section.Value is not string value)
+ {
+ return null;
+ }
+
if (type == typeof(int))
{
- if (section.Value is string stringValue0)
- {
- return ParseInt(stringValue0, () => section.Path);
- }
+ return ParseInt(value, () => section.Path);
}
return null;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
IConfigurationSection section = configuration.GetSection(key);
+ if (section.Value is not string value)
+ {
+ return null;
+ }
+
if (type == typeof(int))
{
- if (section.Value is string stringValue0)
- {
- return ParseInt(stringValue0, () => section.Path);
- }
+ return ParseInt(value, () => section.Path);
}
return null;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
IConfigurationSection section = configuration.GetSection(key);
+ if (section.Value is not string value)
+ {
+ return null;
+ }
+
if (type == typeof(bool?))
{
- if (section.Value is string stringValue0)
- {
- return ParseBool(stringValue0, () => section.Path);
- }
+ return ParseBool(value, () => section.Path);
}
return null;
}
- public static bool ParseBool(string stringValue, Func<string?> getPath)
+ public static bool ParseBool(string value, Func<string?> getPath)
{
try
{
- return bool.Parse(stringValue);
+ return bool.Parse(value);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using Microsoft.Extensions.Configuration;
+ using System;
+ using System.CodeDom.Compiler;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
IConfigurationSection section = configuration.GetSection(key);
+ if (section.Value is not string value)
+ {
+ return null;
+ }
+
if (type == typeof(CultureInfo))
{
- if (section.Value is string stringValue0)
- {
- return ParseCultureInfo(stringValue0, () => section.Path);
- }
+ return ParseCultureInfo(value, () => section.Path);
}
return null;
}
- public static CultureInfo ParseCultureInfo(string stringValue, Func<string?> getPath)
+ public static CultureInfo ParseCultureInfo(string value, Func<string?> getPath)
{
try
{
- return CultureInfo.GetCultureInfo(stringValue);
+ return CultureInfo.GetCultureInfo(value);
}
catch (Exception exception)
{
-// <auto-generated/>
+// <auto-generated/>
#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
{
/// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue1)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue1, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- var temp2 = new List<int>();
- BindCore(configuration, ref temp2, binderOptions);
+ var temp1 = new List<int>();
+ BindCore(configuration, ref temp1, binderOptions);
int originalCount = obj.Length;
- Array.Resize(ref obj, originalCount + temp2.Count);
- temp2.CopyTo(obj, originalCount);
+ Array.Resize(ref obj, originalCount + temp1.Count);
+ temp1.CopyTo(obj, originalCount);
}
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue5)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue5!;
+ obj[section.Key] = value;
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value4)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue7)
- {
- obj.MyInt = ParseInt(stringValue7, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp8 = obj.MyList;
- temp8 ??= new List<int>();
- BindCore(section, ref temp8, binderOptions);
- obj.MyList = temp8;
- }
- }
- break;
- case "MyArray":
- {
- if (HasChildren(section))
- {
- int[] temp9 = obj.MyArray;
- temp9 ??= new int[0];
- BindCore(section, ref temp9, binderOptions);
- obj.MyArray = temp9;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp10 = obj.MyDictionary;
- temp10 ??= new Dictionary<string, string>();
- BindCore(section, ref temp10, binderOptions);
- obj.MyDictionary = temp10;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5)
+ {
+ List<int> temp7 = obj.MyList;
+ temp7 ??= new List<int>();
+ BindCore(section5, ref temp7, binderOptions);
+ obj.MyList = temp7;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyArray")) is IConfigurationSection section8)
+ {
+ int[] temp10 = obj.MyArray;
+ temp10 ??= new int[0];
+ BindCore(section8, ref temp10, binderOptions);
+ obj.MyArray = temp10;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ Dictionary<string, string> temp13 = obj.MyDictionary;
+ temp13 ??= new Dictionary<string, string>();
+ BindCore(section11, ref temp13, binderOptions);
+ obj.MyDictionary = temp13;
+ }
+ }
+
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue1)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue1, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- var temp2 = new List<int>();
- BindCore(configuration, ref temp2, binderOptions);
+ var temp1 = new List<int>();
+ BindCore(configuration, ref temp1, binderOptions);
int originalCount = obj.Length;
- Array.Resize(ref obj, originalCount + temp2.Count);
- temp2.CopyTo(obj, originalCount);
+ Array.Resize(ref obj, originalCount + temp1.Count);
+ temp1.CopyTo(obj, originalCount);
}
public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> obj, BinderOptions? binderOptions)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue5)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue5!;
+ obj[section.Key] = value;
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value4)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue7)
- {
- obj.MyInt = ParseInt(stringValue7, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp8 = obj.MyList;
- temp8 ??= new List<int>();
- BindCore(section, ref temp8, binderOptions);
- obj.MyList = temp8;
- }
- }
- break;
- case "MyArray":
- {
- if (HasChildren(section))
- {
- int[] temp9 = obj.MyArray;
- temp9 ??= new int[0];
- BindCore(section, ref temp9, binderOptions);
- obj.MyArray = temp9;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp10 = obj.MyDictionary;
- temp10 ??= new Dictionary<string, string>();
- BindCore(section, ref temp10, binderOptions);
- obj.MyDictionary = temp10;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5)
+ {
+ List<int> temp7 = obj.MyList;
+ temp7 ??= new List<int>();
+ BindCore(section5, ref temp7, binderOptions);
+ obj.MyList = temp7;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyArray")) is IConfigurationSection section8)
+ {
+ int[] temp10 = obj.MyArray;
+ temp10 ??= new int[0];
+ BindCore(section8, ref temp10, binderOptions);
+ obj.MyArray = temp10;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ Dictionary<string, string> temp13 = obj.MyDictionary;
+ temp13 ??= new Dictionary<string, string>();
+ BindCore(section11, ref temp13, binderOptions);
+ obj.MyDictionary = temp13;
+ }
+ }
+
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
+
+ if (configuration["MyInt"] is string value1)
{
- switch (section.Key)
- {
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue1)
- {
- obj.MyInt = ParseInt(stringValue1, () => section.Path)!;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
}
+ }
- if (temp is not null)
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass2)}: {string.Join(", ", temp)}");
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
+
+ if (configuration["MyInt"] is string value1)
{
- switch (section.Key)
- {
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue1)
- {
- obj.MyInt = ParseInt(stringValue1, () => section.Path)!;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
}
+ }
- if (temp is not null)
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass2)}: {string.Join(", ", temp)}");
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
-// <auto-generated/>
+// <auto-generated/>
#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
{
/// <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>
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue1)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue1, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value2)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue3)
- {
- obj.MyInt = ParseInt(stringValue3, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp4 = obj.MyList;
- temp4 ??= new List<int>();
- BindCore(section, ref temp4, binderOptions);
- obj.MyList = temp4;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value2, () => configuration.GetSection("MyInt").Path);
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section3)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ List<int> temp5 = obj.MyList;
+ temp5 ??= new List<int>();
+ BindCore(section3, ref temp5, binderOptions);
+ obj.MyList = temp5;
+ }
+ }
+
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Registers a configuration instance which <typeparamref name="TOptions"/> will bind against.</summary>
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
{
}
/// <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>
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue1)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue1, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value2)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue3)
- {
- obj.MyInt = ParseInt(stringValue3, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp4 = obj.MyList;
- temp4 ??= new List<int>();
- BindCore(section, ref temp4, binderOptions);
- obj.MyList = temp4;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value2, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section3)
+ {
+ List<int> temp5 = obj.MyList;
+ temp5 ??= new List<int>();
+ BindCore(section3, ref temp5, binderOptions);
+ obj.MyList = temp5;
}
+ }
- if (temp is not null)
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Registers a configuration instance which <typeparamref name="TOptions"/> will bind against.</summary>
}
/// <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>
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue1)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue1, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value2)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue3)
- {
- obj.MyInt = ParseInt(stringValue3, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp4 = obj.MyList;
- temp4 ??= new List<int>();
- BindCore(section, ref temp4, binderOptions);
- obj.MyList = temp4;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value2, () => configuration.GetSection("MyInt").Path);
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section3)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ List<int> temp5 = obj.MyList;
+ temp5 ??= new List<int>();
+ BindCore(section3, ref temp5, binderOptions);
+ obj.MyList = temp5;
+ }
+ }
+
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (obj is null)
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ if (configuration["Prop0"] is string value0)
{
- switch (section.Key)
- {
- case "Prop0":
- {
- if (configuration["Prop0"] is string stringValue0)
- {
- obj.Prop0 = ParseBool(stringValue0, () => section.Path)!;
- }
- }
- break;
- case "Prop1":
- {
- if (configuration["Prop1"] is string stringValue1)
- {
- obj.Prop1 = ParseByte(stringValue1, () => section.Path)!;
- }
- }
- break;
- case "Prop2":
- {
- if (configuration["Prop2"] is string stringValue2)
- {
- obj.Prop2 = ParseSbyte(stringValue2, () => section.Path)!;
- }
- }
- break;
- case "Prop3":
- {
- if (configuration["Prop3"] is string stringValue3)
- {
- obj.Prop3 = ParseChar(stringValue3, () => section.Path)!;
- }
- }
- break;
- case "Prop4":
- {
- if (configuration["Prop4"] is string stringValue4)
- {
- obj.Prop4 = ParseDouble(stringValue4, () => section.Path)!;
- }
- }
- break;
- case "Prop5":
- {
- obj.Prop5 = configuration["Prop5"]!;
- }
- break;
- case "Prop6":
- {
- if (configuration["Prop6"] is string stringValue6)
- {
- obj.Prop6 = ParseInt(stringValue6, () => section.Path)!;
- }
- }
- break;
- case "Prop8":
- {
- if (configuration["Prop8"] is string stringValue7)
- {
- obj.Prop8 = ParseShort(stringValue7, () => section.Path)!;
- }
- }
- break;
- case "Prop9":
- {
- if (configuration["Prop9"] is string stringValue8)
- {
- obj.Prop9 = ParseLong(stringValue8, () => section.Path)!;
- }
- }
- break;
- case "Prop10":
- {
- if (configuration["Prop10"] is string stringValue9)
- {
- obj.Prop10 = ParseFloat(stringValue9, () => section.Path)!;
- }
- }
- break;
- case "Prop13":
- {
- if (configuration["Prop13"] is string stringValue10)
- {
- obj.Prop13 = ParseUshort(stringValue10, () => section.Path)!;
- }
- }
- break;
- case "Prop14":
- {
- if (configuration["Prop14"] is string stringValue11)
- {
- obj.Prop14 = ParseUint(stringValue11, () => section.Path)!;
- }
- }
- break;
- case "Prop15":
- {
- if (configuration["Prop15"] is string stringValue12)
- {
- obj.Prop15 = ParseUlong(stringValue12, () => section.Path)!;
- }
- }
- break;
- case "Prop16":
- {
- obj.Prop16 = configuration["Prop16"]!;
- }
- break;
- case "Prop17":
- {
- if (configuration["Prop17"] is string stringValue14)
- {
- obj.Prop17 = ParseCultureInfo(stringValue14, () => section.Path)!;
- }
- }
- break;
- case "Prop19":
- {
- if (configuration["Prop19"] is string stringValue15)
- {
- obj.Prop19 = ParseDateTime(stringValue15, () => section.Path)!;
- }
- }
- break;
- case "Prop20":
- {
- if (configuration["Prop20"] is string stringValue16)
- {
- obj.Prop20 = ParseDateTimeOffset(stringValue16, () => section.Path)!;
- }
- }
- break;
- case "Prop21":
- {
- if (configuration["Prop21"] is string stringValue17)
- {
- obj.Prop21 = ParseDecimal(stringValue17, () => section.Path)!;
- }
- }
- break;
- case "Prop23":
- {
- if (configuration["Prop23"] is string stringValue18)
- {
- obj.Prop23 = ParseInt(stringValue18, () => section.Path)!;
- }
- }
- break;
- case "Prop24":
- {
- if (configuration["Prop24"] is string stringValue19)
- {
- obj.Prop24 = ParseDateTime(stringValue19, () => section.Path)!;
- }
- }
- break;
- case "Prop25":
- {
- if (configuration["Prop25"] is string stringValue20)
- {
- obj.Prop25 = ParseUri(stringValue20, () => section.Path)!;
- }
- }
- break;
- case "Prop26":
- {
- if (configuration["Prop26"] is string stringValue21)
- {
- obj.Prop26 = ParseVersion(stringValue21, () => section.Path)!;
- }
- }
- break;
- case "Prop27":
- {
- if (configuration["Prop27"] is string stringValue22)
- {
- obj.Prop27 = ParseDayOfWeek(stringValue22, () => section.Path)!;
- }
- }
- break;
- case "Prop7":
- {
- if (configuration["Prop7"] is string stringValue23)
- {
- obj.Prop7 = ParseInt128(stringValue23, () => section.Path)!;
- }
- }
- break;
- case "Prop11":
- {
- if (configuration["Prop11"] is string stringValue24)
- {
- obj.Prop11 = ParseHalf(stringValue24, () => section.Path)!;
- }
- }
- break;
- case "Prop12":
- {
- if (configuration["Prop12"] is string stringValue25)
- {
- obj.Prop12 = ParseUInt128(stringValue25, () => section.Path)!;
- }
- }
- break;
- case "Prop18":
- {
- if (configuration["Prop18"] is string stringValue26)
- {
- obj.Prop18 = ParseDateOnly(stringValue26, () => section.Path)!;
- }
- }
- break;
- case "Prop22":
- {
- if (configuration["Prop22"] is string stringValue27)
- {
- obj.Prop22 = ParseByteArray(stringValue27, () => section.Path)!;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.Prop0 = ParseBool(value0, () => configuration.GetSection("Prop0").Path);
+ }
+
+ if (configuration["Prop1"] is string value1)
+ {
+ obj.Prop1 = ParseByte(value1, () => configuration.GetSection("Prop1").Path);
+ }
+
+ if (configuration["Prop2"] is string value2)
+ {
+ obj.Prop2 = ParseSbyte(value2, () => configuration.GetSection("Prop2").Path);
+ }
+
+ if (configuration["Prop3"] is string value3)
+ {
+ obj.Prop3 = ParseChar(value3, () => configuration.GetSection("Prop3").Path);
+ }
+
+ if (configuration["Prop4"] is string value4)
+ {
+ obj.Prop4 = ParseDouble(value4, () => configuration.GetSection("Prop4").Path);
+ }
+
+ obj.Prop5 = configuration["Prop5"]!;
+
+ if (configuration["Prop6"] is string value6)
+ {
+ obj.Prop6 = ParseInt(value6, () => configuration.GetSection("Prop6").Path);
+ }
+
+ if (configuration["Prop8"] is string value7)
+ {
+ obj.Prop8 = ParseShort(value7, () => configuration.GetSection("Prop8").Path);
+ }
+
+ if (configuration["Prop9"] is string value8)
+ {
+ obj.Prop9 = ParseLong(value8, () => configuration.GetSection("Prop9").Path);
+ }
+
+ if (configuration["Prop10"] is string value9)
+ {
+ obj.Prop10 = ParseFloat(value9, () => configuration.GetSection("Prop10").Path);
+ }
+
+ if (configuration["Prop13"] is string value10)
+ {
+ obj.Prop13 = ParseUshort(value10, () => configuration.GetSection("Prop13").Path);
+ }
+
+ if (configuration["Prop14"] is string value11)
+ {
+ obj.Prop14 = ParseUint(value11, () => configuration.GetSection("Prop14").Path);
+ }
+
+ if (configuration["Prop15"] is string value12)
+ {
+ obj.Prop15 = ParseUlong(value12, () => configuration.GetSection("Prop15").Path);
}
- if (temp is not null)
+ obj.Prop16 = configuration["Prop16"]!;
+
+ if (configuration["Prop17"] is string value14)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ obj.Prop17 = ParseCultureInfo(value14, () => configuration.GetSection("Prop17").Path);
+ }
+
+ if (configuration["Prop19"] is string value15)
+ {
+ obj.Prop19 = ParseDateTime(value15, () => configuration.GetSection("Prop19").Path);
+ }
+
+ if (configuration["Prop20"] is string value16)
+ {
+ obj.Prop20 = ParseDateTimeOffset(value16, () => configuration.GetSection("Prop20").Path);
+ }
+
+ if (configuration["Prop21"] is string value17)
+ {
+ obj.Prop21 = ParseDecimal(value17, () => configuration.GetSection("Prop21").Path);
+ }
+
+ if (configuration["Prop23"] is string value18)
+ {
+ obj.Prop23 = ParseInt(value18, () => configuration.GetSection("Prop23").Path);
+ }
+
+ if (configuration["Prop24"] is string value19)
+ {
+ obj.Prop24 = ParseDateTime(value19, () => configuration.GetSection("Prop24").Path);
+ }
+
+ if (configuration["Prop25"] is string value20)
+ {
+ obj.Prop25 = ParseUri(value20, () => configuration.GetSection("Prop25").Path);
+ }
+
+ if (configuration["Prop26"] is string value21)
+ {
+ obj.Prop26 = ParseVersion(value21, () => configuration.GetSection("Prop26").Path);
+ }
+
+ if (configuration["Prop27"] is string value22)
+ {
+ obj.Prop27 = ParseDayOfWeek(value22, () => configuration.GetSection("Prop27").Path);
+ }
+
+ if (configuration["Prop7"] is string value23)
+ {
+ obj.Prop7 = ParseInt128(value23, () => configuration.GetSection("Prop7").Path);
+ }
+
+ if (configuration["Prop11"] is string value24)
+ {
+ obj.Prop11 = ParseHalf(value24, () => configuration.GetSection("Prop11").Path);
+ }
+
+ if (configuration["Prop12"] is string value25)
+ {
+ obj.Prop12 = ParseUInt128(value25, () => configuration.GetSection("Prop12").Path);
+ }
+
+ if (configuration["Prop18"] is string value26)
+ {
+ obj.Prop18 = ParseDateOnly(value26, () => configuration.GetSection("Prop18").Path);
+ }
+
+ if (configuration["Prop22"] is string value27)
+ {
+ obj.Prop22 = ParseByteArray(value27, () => configuration.GetSection("Prop22").Path);
+ }
+ }
+
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
- public static bool ParseBool(string stringValue, Func<string?> getPath)
+ public static bool ParseBool(string value, Func<string?> getPath)
{
try
{
- return bool.Parse(stringValue);
+ return bool.Parse(value);
}
catch (Exception exception)
{
}
}
- public static byte ParseByte(string stringValue, Func<string?> getPath)
+ public static byte ParseByte(string value, Func<string?> getPath)
{
try
{
- return byte.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return byte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static sbyte ParseSbyte(string stringValue, Func<string?> getPath)
+ public static sbyte ParseSbyte(string value, Func<string?> getPath)
{
try
{
- return sbyte.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return sbyte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static char ParseChar(string stringValue, Func<string?> getPath)
+ public static char ParseChar(string value, Func<string?> getPath)
{
try
{
- return char.Parse(stringValue);
+ return char.Parse(value);
}
catch (Exception exception)
{
}
}
- public static double ParseDouble(string stringValue, Func<string?> getPath)
+ public static double ParseDouble(string value, Func<string?> getPath)
{
try
{
- return double.Parse(stringValue, NumberStyles.Float, CultureInfo.InvariantCulture);
+ return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static short ParseShort(string stringValue, Func<string?> getPath)
+ public static short ParseShort(string value, Func<string?> getPath)
{
try
{
- return short.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return short.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static long ParseLong(string stringValue, Func<string?> getPath)
+ public static long ParseLong(string value, Func<string?> getPath)
{
try
{
- return long.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static float ParseFloat(string stringValue, Func<string?> getPath)
+ public static float ParseFloat(string value, Func<string?> getPath)
{
try
{
- return float.Parse(stringValue, NumberStyles.Float, CultureInfo.InvariantCulture);
+ return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static ushort ParseUshort(string stringValue, Func<string?> getPath)
+ public static ushort ParseUshort(string value, Func<string?> getPath)
{
try
{
- return ushort.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return ushort.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static uint ParseUint(string stringValue, Func<string?> getPath)
+ public static uint ParseUint(string value, Func<string?> getPath)
{
try
{
- return uint.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return uint.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static ulong ParseUlong(string stringValue, Func<string?> getPath)
+ public static ulong ParseUlong(string value, Func<string?> getPath)
{
try
{
- return ulong.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return ulong.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static CultureInfo ParseCultureInfo(string stringValue, Func<string?> getPath)
+ public static CultureInfo ParseCultureInfo(string value, Func<string?> getPath)
{
try
{
- return CultureInfo.GetCultureInfo(stringValue);
+ return CultureInfo.GetCultureInfo(value);
}
catch (Exception exception)
{
}
}
- public static DateTime ParseDateTime(string stringValue, Func<string?> getPath)
+ public static DateTime ParseDateTime(string value, Func<string?> getPath)
{
try
{
- return DateTime.Parse(stringValue, CultureInfo.InvariantCulture);
+ return DateTime.Parse(value, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static DateTimeOffset ParseDateTimeOffset(string stringValue, Func<string?> getPath)
+ public static DateTimeOffset ParseDateTimeOffset(string value, Func<string?> getPath)
{
try
{
- return DateTimeOffset.Parse(stringValue, CultureInfo.InvariantCulture);
+ return DateTimeOffset.Parse(value, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static decimal ParseDecimal(string stringValue, Func<string?> getPath)
+ public static decimal ParseDecimal(string value, Func<string?> getPath)
{
try
{
- return decimal.Parse(stringValue, NumberStyles.Float, CultureInfo.InvariantCulture);
+ return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static TimeSpan ParseTimeSpan(string stringValue, Func<string?> getPath)
+ public static TimeSpan ParseTimeSpan(string value, Func<string?> getPath)
{
try
{
- return TimeSpan.Parse(stringValue, CultureInfo.InvariantCulture);
+ return TimeSpan.Parse(value, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static Guid ParseGuid(string stringValue, Func<string?> getPath)
+ public static Guid ParseGuid(string value, Func<string?> getPath)
{
try
{
- return Guid.Parse(stringValue);
+ return Guid.Parse(value);
}
catch (Exception exception)
{
}
}
- public static Uri ParseUri(string stringValue, Func<string?> getPath)
+ public static Uri ParseUri(string value, Func<string?> getPath)
{
try
{
- return new Uri(stringValue, UriKind.RelativeOrAbsolute);
+ return new Uri(value, UriKind.RelativeOrAbsolute);
}
catch (Exception exception)
{
}
}
- public static Version ParseVersion(string stringValue, Func<string?> getPath)
+ public static Version ParseVersion(string value, Func<string?> getPath)
{
try
{
- return Version.Parse(stringValue);
+ return Version.Parse(value);
}
catch (Exception exception)
{
}
}
- public static DayOfWeek ParseDayOfWeek(string stringValue, Func<string?> getPath)
+ public static DayOfWeek ParseDayOfWeek(string value, Func<string?> getPath)
{
try
{
- return (DayOfWeek)Enum.Parse(typeof(DayOfWeek), stringValue, ignoreCase: true);
+ return (DayOfWeek)Enum.Parse(typeof(DayOfWeek), value, ignoreCase: true);
}
catch (Exception exception)
{
}
}
- public static Int128 ParseInt128(string stringValue, Func<string?> getPath)
+ public static Int128 ParseInt128(string value, Func<string?> getPath)
{
try
{
- return Int128.Parse(stringValue, CultureInfo.InvariantCulture);
+ return Int128.Parse(value, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static Half ParseHalf(string stringValue, Func<string?> getPath)
+ public static Half ParseHalf(string value, Func<string?> getPath)
{
try
{
- return Half.Parse(stringValue, CultureInfo.InvariantCulture);
+ return Half.Parse(value, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static UInt128 ParseUInt128(string stringValue, Func<string?> getPath)
+ public static UInt128 ParseUInt128(string value, Func<string?> getPath)
{
try
{
- return UInt128.Parse(stringValue, CultureInfo.InvariantCulture);
+ return UInt128.Parse(value, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static DateOnly ParseDateOnly(string stringValue, Func<string?> getPath)
+ public static DateOnly ParseDateOnly(string value, Func<string?> getPath)
{
try
{
- return DateOnly.Parse(stringValue, CultureInfo.InvariantCulture);
+ return DateOnly.Parse(value, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static TimeOnly ParseTimeOnly(string stringValue, Func<string?> getPath)
+ public static TimeOnly ParseTimeOnly(string value, Func<string?> getPath)
{
try
{
- return TimeOnly.Parse(stringValue, CultureInfo.InvariantCulture);
+ return TimeOnly.Parse(value, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
}
}
- public static byte[] ParseByteArray(string stringValue, Func<string?> getPath)
+ public static byte[] ParseByteArray(string value, Func<string?> getPath)
{
try
{
- return Convert.FromBase64String(stringValue);
+ return Convert.FromBase64String(value);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Registers a configuration instance which TOptions will bind against.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue1)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue1, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
- {
- switch (section.Key)
- {
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue2)
- {
- obj.MyInt = ParseInt(stringValue2, () => section.Path)!;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
- }
+ ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
- if (temp is not null)
+ if (configuration["MyInt"] is string value1)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass2)}: {string.Join(", ", temp)}");
+ obj.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- var element = new Program.MyClass2();
- BindCore(section, ref element, binderOptions);
- obj.Add(element);
+ var value = new Program.MyClass2();
+ BindCore(section, ref value, binderOptions);
+ obj.Add(value);
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue5)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue5!;
+ obj[section.Key] = value;
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value4)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue7)
- {
- obj.MyInt = ParseInt(stringValue7, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp8 = obj.MyList;
- temp8 ??= new List<int>();
- BindCore(section, ref temp8, binderOptions);
- obj.MyList = temp8;
- }
- }
- break;
- case "MyList2":
- {
- if (HasChildren(section))
- {
- List<Program.MyClass2> temp9 = obj.MyList2;
- temp9 ??= new List<Program.MyClass2>();
- BindCore(section, ref temp9, binderOptions);
- obj.MyList2 = temp9;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp10 = obj.MyDictionary;
- temp10 ??= new Dictionary<string, string>();
- BindCore(section, ref temp10, binderOptions);
- obj.MyDictionary = temp10;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5)
+ {
+ List<int> temp7 = obj.MyList;
+ temp7 ??= new List<int>();
+ BindCore(section5, ref temp7, binderOptions);
+ obj.MyList = temp7;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyList2")) is IConfigurationSection section8)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ List<Program.MyClass2> temp10 = obj.MyList2;
+ temp10 ??= new List<Program.MyClass2>();
+ BindCore(section8, ref temp10, binderOptions);
+ obj.MyList2 = temp10;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11)
+ {
+ Dictionary<string, string> temp13 = obj.MyDictionary;
+ temp13 ??= new Dictionary<string, string>();
+ BindCore(section11, ref temp13, binderOptions);
+ obj.MyDictionary = temp13;
+ }
+ }
+
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Registers a configuration instance which TOptions will bind against.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue1)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue1, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
- {
- switch (section.Key)
- {
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue2)
- {
- obj.MyInt = ParseInt(stringValue2, () => section.Path)!;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
- }
+ ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
- if (temp is not null)
+ if (configuration["MyInt"] is string value1)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass2)}: {string.Join(", ", temp)}");
+ obj.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- var element = new Program.MyClass2();
- BindCore(section, ref element, binderOptions);
- obj.Add(element);
+ var value = new Program.MyClass2();
+ BindCore(section, ref value, binderOptions);
+ obj.Add(value);
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue5)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue5!;
+ obj[section.Key] = value;
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value4)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue7)
- {
- obj.MyInt = ParseInt(stringValue7, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp8 = obj.MyList;
- temp8 ??= new List<int>();
- BindCore(section, ref temp8, binderOptions);
- obj.MyList = temp8;
- }
- }
- break;
- case "MyList2":
- {
- if (HasChildren(section))
- {
- List<Program.MyClass2> temp9 = obj.MyList2;
- temp9 ??= new List<Program.MyClass2>();
- BindCore(section, ref temp9, binderOptions);
- obj.MyList2 = temp9;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp10 = obj.MyDictionary;
- temp10 ??= new Dictionary<string, string>();
- BindCore(section, ref temp10, binderOptions);
- obj.MyDictionary = temp10;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5)
+ {
+ List<int> temp7 = obj.MyList;
+ temp7 ??= new List<int>();
+ BindCore(section5, ref temp7, binderOptions);
+ obj.MyList = temp7;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyList2")) is IConfigurationSection section8)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ List<Program.MyClass2> temp10 = obj.MyList2;
+ temp10 ??= new List<Program.MyClass2>();
+ BindCore(section8, ref temp10, binderOptions);
+ obj.MyList2 = temp10;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11)
+ {
+ Dictionary<string, string> temp13 = obj.MyDictionary;
+ temp13 ??= new Dictionary<string, string>();
+ BindCore(section11, ref temp13, binderOptions);
+ obj.MyDictionary = temp13;
+ }
+ }
+
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Registers a configuration instance which TOptions will bind against.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue1)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue1, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
- {
- switch (section.Key)
- {
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue2)
- {
- obj.MyInt = ParseInt(stringValue2, () => section.Path)!;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
- }
+ ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
- if (temp is not null)
+ if (configuration["MyInt"] is string value1)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass2)}: {string.Join(", ", temp)}");
+ obj.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- var element = new Program.MyClass2();
- BindCore(section, ref element, binderOptions);
- obj.Add(element);
+ var value = new Program.MyClass2();
+ BindCore(section, ref value, binderOptions);
+ obj.Add(value);
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue5)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue5!;
+ obj[section.Key] = value;
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value4)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue7)
- {
- obj.MyInt = ParseInt(stringValue7, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp8 = obj.MyList;
- temp8 ??= new List<int>();
- BindCore(section, ref temp8, binderOptions);
- obj.MyList = temp8;
- }
- }
- break;
- case "MyList2":
- {
- if (HasChildren(section))
- {
- List<Program.MyClass2> temp9 = obj.MyList2;
- temp9 ??= new List<Program.MyClass2>();
- BindCore(section, ref temp9, binderOptions);
- obj.MyList2 = temp9;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp10 = obj.MyDictionary;
- temp10 ??= new Dictionary<string, string>();
- BindCore(section, ref temp10, binderOptions);
- obj.MyDictionary = temp10;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5)
+ {
+ List<int> temp7 = obj.MyList;
+ temp7 ??= new List<int>();
+ BindCore(section5, ref temp7, binderOptions);
+ obj.MyList = temp7;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyList2")) is IConfigurationSection section8)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ List<Program.MyClass2> temp10 = obj.MyList2;
+ temp10 ??= new List<Program.MyClass2>();
+ BindCore(section8, ref temp10, binderOptions);
+ obj.MyList2 = temp10;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11)
+ {
+ Dictionary<string, string> temp13 = obj.MyDictionary;
+ temp13 ??= new Dictionary<string, string>();
+ BindCore(section11, ref temp13, binderOptions);
+ obj.MyDictionary = temp13;
+ }
+ }
+
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
// <auto-generated/>
#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
{
/// <summary>Registers a configuration instance which TOptions will bind against.</summary>
{
using Microsoft.Extensions.Configuration;
using System;
+ using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
/// <summary>Provide core binding logic.</summary>
- internal static class CoreBindingHelper
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ file static class CoreBindingHelper
{
+ 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)
{
if (configuration is null)
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue1)
+ if (section.Value is string value)
{
- obj.Add(ParseInt(stringValue1, () => section.Path)!);
+ obj.Add(ParseInt(value, () => section.Path));
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
- {
- switch (section.Key)
- {
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue2)
- {
- obj.MyInt = ParseInt(stringValue2, () => section.Path)!;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
- }
+ ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
- if (temp is not null)
+ if (configuration["MyInt"] is string value1)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass2)}: {string.Join(", ", temp)}");
+ obj.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- var element = new Program.MyClass2();
- BindCore(section, ref element, binderOptions);
- obj.Add(element);
+ var value = new Program.MyClass2();
+ BindCore(section, ref value, binderOptions);
+ obj.Add(value);
}
}
foreach (IConfigurationSection section in configuration.GetChildren())
{
- if (section.Value is string stringValue5)
+ if (section.Value is string value)
{
- obj[section.Key!] = stringValue5!;
+ obj[section.Key] = value;
}
}
}
throw new ArgumentNullException(nameof(obj));
}
- List<string>? temp = null;
- foreach (IConfigurationSection section in configuration.GetChildren())
+ ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
+
+ obj.MyString = configuration["MyString"]!;
+
+ if (configuration["MyInt"] is string value4)
{
- switch (section.Key)
- {
- case "MyString":
- {
- obj.MyString = configuration["MyString"]!;
- }
- break;
- case "MyInt":
- {
- if (configuration["MyInt"] is string stringValue7)
- {
- obj.MyInt = ParseInt(stringValue7, () => section.Path)!;
- }
- }
- break;
- case "MyList":
- {
- if (HasChildren(section))
- {
- List<int> temp8 = obj.MyList;
- temp8 ??= new List<int>();
- BindCore(section, ref temp8, binderOptions);
- obj.MyList = temp8;
- }
- }
- break;
- case "MyList2":
- {
- if (HasChildren(section))
- {
- List<Program.MyClass2> temp9 = obj.MyList2;
- temp9 ??= new List<Program.MyClass2>();
- BindCore(section, ref temp9, binderOptions);
- obj.MyList2 = temp9;
- }
- }
- break;
- case "MyDictionary":
- {
- if (HasChildren(section))
- {
- Dictionary<string, string> temp10 = obj.MyDictionary;
- temp10 ??= new Dictionary<string, string>();
- BindCore(section, ref temp10, binderOptions);
- obj.MyDictionary = temp10;
- }
- }
- break;
- default:
- {
- if (binderOptions?.ErrorOnUnknownConfiguration == true)
- {
- (temp ??= new List<string>()).Add($"'{section.Key}'");
- }
- }
- break;
- }
+ obj.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path);
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5)
+ {
+ List<int> temp7 = obj.MyList;
+ temp7 ??= new List<int>();
+ BindCore(section5, ref temp7, binderOptions);
+ obj.MyList = temp7;
}
- if (temp is not null)
+ if (AsConfigWithChildren(configuration.GetSection("MyList2")) is IConfigurationSection section8)
{
- throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}");
+ List<Program.MyClass2> temp10 = obj.MyList2;
+ temp10 ??= new List<Program.MyClass2>();
+ BindCore(section8, ref temp10, binderOptions);
+ obj.MyList2 = temp10;
+ }
+
+ if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11)
+ {
+ Dictionary<string, string> temp13 = obj.MyDictionary;
+ temp13 ??= new Dictionary<string, string>();
+ BindCore(section11, ref temp13, binderOptions);
+ obj.MyDictionary = temp13;
+ }
+ }
+
+ /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
+ public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
+ {
+ if (binderOptions?.ErrorOnUnknownConfiguration is true)
+ {
+ List<string>? temp = null;
+ foreach (IConfigurationSection section in configuration.GetChildren())
+ {
+ if (!keys.Value.Contains(section.Key))
+ {
+ (temp ??= new List<string>()).Add($"'{section.Key}'");
+ }
+ }
+ if (temp is not null)
+ {
+ throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
+ }
}
}
{
return true;
}
- return HasChildren(configuration);
+ return AsConfigWithChildren(configuration) is not null;
}
- public static bool HasChildren(IConfiguration configuration)
+ public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
- foreach (IConfigurationSection section in configuration.GetChildren())
+ foreach (IConfigurationSection _ in configuration.GetChildren())
{
- return true;
+ return configuration;
}
- return false;
+ return null;
}
public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
return binderOptions;
}
- public static int ParseInt(string stringValue, Func<string?> getPath)
+ public static int ParseInt(string value, Func<string?> getPath)
{
try
{
- return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
+using Microsoft.Extensions.SourceGeneration.Configuration.Binder.Tests;
using SourceGenerators.Tests;
using Xunit;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests
{
[ActiveIssue("https://github.com/dotnet/runtime/issues/52062", TestPlatforms.Browser)]
- public partial class ConfigurationBindingGeneratorTests
+ public partial class ConfigurationBindingGeneratorTests : ConfigurationBinderTestsBase
{
private static class Diagnostics
{
}
}
+ [Fact]
+ public async Task BindCanParseMethodParam()
+ {
+ string source = """
+ using System;
+ using Microsoft.AspNetCore.Builder;
+ using Microsoft.Extensions.Configuration;
+ using Microsoft.Extensions.DependencyInjection;
+
+ public class Program
+ {
+ public static void Main()
+ {
+ ConfigurationBuilder configurationBuilder = new();
+ IConfiguration config = configurationBuilder.Build();
+
+ BindOptions(config, new MyClass0());
+ BindOptions(config, new MyClass1(), (_) => { });
+ BindOptions(config, "", new MyClass2());
+ }
+
+ private void BindOptions(IConfiguration config, MyClass0 instance)
+ {
+ config.Bind(instance);
+ }
+
+ private void BindOptions(IConfiguration config, MyClass1 instance, Action<BinderOptions>? configureOptions)
+ {
+ config.Bind(instance, configureOptions);
+ }
+
+ private void BindOptions(IConfiguration config, string path, MyClass2 instance)
+ {
+ config.Bind(path, instance);
+ }
+
+ public class MyClass0 { }
+ public class MyClass1 { }
+ public class MyClass2 { }
+ }
+ """;
+
+ var (d, r) = await RunGenerator(source);
+ 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.Empty(d);
+ }
+
private static async Task VerifyAgainstBaselineUsingFile(
string filename,
string testSourceCode,
.Split(Environment.NewLine);
var (d, r) = await RunGenerator(testSourceCode, languageVersion);
+ bool success = RoslynTestUtils.CompareLines(expectedLines, r[0].SourceText,
+ out string errorMessage);
+#if !SKIP_BASELINES
Assert.Single(r);
(assessDiagnostics ?? ((d) => Assert.Empty(d))).Invoke(d);
-
- Assert.True(RoslynTestUtils.CompareLines(expectedLines, r[0].SourceText,
- out string errorMessage), errorMessage);
+ Assert.True(success, errorMessage);
+#endif
}
private static async Task<(ImmutableArray<Diagnostic>, ImmutableArray<GeneratedSourceResult>)> RunGenerator(
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkMinimum)</TargetFrameworks>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
- <DefineConstants>$(DefineConstants);BUILDING_SOURCE_GENERATOR_TESTS;ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER</DefineConstants>
<!-- Type not supported; property on type not suppported; value types invalid for bind; generator could not parse target type -->
<NoWarn>SYSLIB1100,SYSLIB1101,SYSLIB1103,SYSLIB1104</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. -->
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>
+ <PropertyGroup>
+ <DefineConstants>$(DefineConstants);BUILDING_SOURCE_GENERATOR_TESTS;ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER</DefineConstants>
+ <DefineConstants Condition="'$(LaunchTestDebugger)' == 'true'">$(DefineConstants);LAUNCH_DEBUGGER</DefineConstants>
+ <DefineConstants Condition="'$(SkipBaselines)' == 'true'">$(DefineConstants);SKIP_BASELINES</DefineConstants>
+ </PropertyGroup>
+
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<Compile Include="$(CoreLibSharedDir)System\Runtime\Versioning\RequiresPreviewFeaturesAttribute.cs" Link="System\Runtime\Versioning\RequiresPreviewFeaturesAttribute.cs" />
</ItemGroup>