Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ private void ParseBindInvocation_ConfigurationBinder(BinderInvocation invocation
_ => throw new InvalidOperationException()
};

IArgumentOperation instanceArg = operation.Arguments[instanceIndex];
IArgumentOperation instanceArg = GetArgumentForParameterAtIndex(operation.Arguments, instanceIndex);
if (instanceArg.Parameter.Type.SpecialType != SpecialType.System_Object)
{
return;
Expand Down Expand Up @@ -119,6 +119,19 @@ private void ParseBindInvocation_ConfigurationBinder(BinderInvocation invocation
};
}

private static IArgumentOperation GetArgumentForParameterAtIndex(ImmutableArray<IArgumentOperation> arguments, int parameterIndex)
{
foreach (var argument in arguments)
{
if (argument.Parameter?.Ordinal == parameterIndex)
{
return argument;
}
}

throw new InvalidOperationException();
}

private void ParseGetInvocation(BinderInvocation invocation)
{
IInvocationOperation operation = invocation.Operation!;
Expand Down Expand Up @@ -158,7 +171,7 @@ private void ParseGetInvocation(BinderInvocation invocation)
}
else
{
ITypeOfOperation? typeOfOperation = operation.Arguments[1].ChildOperations.FirstOrDefault() as ITypeOfOperation;
ITypeOfOperation? typeOfOperation = GetArgumentForParameterAtIndex(operation.Arguments, 1).ChildOperations.FirstOrDefault() as ITypeOfOperation;
type = typeOfOperation?.TypeOperand;

if (paramCount is 2)
Expand Down Expand Up @@ -218,7 +231,7 @@ private void ParseGetValueInvocation(BinderInvocation invocation)
return;
}

ITypeOfOperation? typeOfOperation = operation.Arguments[1].ChildOperations.FirstOrDefault() as ITypeOfOperation;
ITypeOfOperation? typeOfOperation = GetArgumentForParameterAtIndex(operation.Arguments, 1).ChildOperations.FirstOrDefault() as ITypeOfOperation;
type = typeOfOperation?.TypeOperand;

if (paramCount is 3)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// <auto-generated/>
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.

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

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

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

[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
file static class BindingExtensions
{
#region IConfiguration extensions.
/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
[InterceptsLocation(@"src-0.cs", 12, 33)]
public static void Bind_ProgramMyClass(this IConfiguration configuration, object? instance)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}

if (instance is null)
{
return;
}

var typedObj = (Program.MyClass)instance;
BindCore(configuration, ref typedObj, binderOptions: null);
}
#endregion IConfiguration extensions.

#region Core binding extensions.
private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClass = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });

public static void BindCore(IConfiguration configuration, ref List<int> instance, BinderOptions? binderOptions)
{
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
{
instance.Add(ParseInt(value, () => section.Path));
}
}
}

public static void BindCore(IConfiguration configuration, ref Dictionary<string, string> instance, BinderOptions? binderOptions)
{
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
{
instance[section.Key] = value;
}
}
}

public static void BindCore(IConfiguration configuration, ref Dictionary<string, Program.MyClass2> instance, BinderOptions? binderOptions)
{
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!(instance.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
{
element = new Program.MyClass2();
}
instance[section.Key] = element;
}
}

public static void BindCore(IConfiguration configuration, ref Program.MyClass instance, BinderOptions? binderOptions)
{
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);

instance.MyString = configuration["MyString"]!;

if (configuration["MyInt"] is string value1)
{
instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path);
}

if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section2)
{
List<int>? temp4 = instance.MyList;
temp4 ??= new List<int>();
BindCore(section2, ref temp4, binderOptions);
instance.MyList = temp4;
}

if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section5)
{
Dictionary<string, string>? temp7 = instance.MyDictionary;
temp7 ??= new Dictionary<string, string>();
BindCore(section5, ref temp7, binderOptions);
instance.MyDictionary = temp7;
}

if (AsConfigWithChildren(configuration.GetSection("MyComplexDictionary")) is IConfigurationSection section8)
{
Dictionary<string, Program.MyClass2>? temp10 = instance.MyComplexDictionary;
temp10 ??= new Dictionary<string, Program.MyClass2>();
BindCore(section8, ref temp10, binderOptions);
instance.MyComplexDictionary = temp10;
}
}


/// <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 IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
foreach (IConfigurationSection _ in configuration.GetChildren())
{
return configuration;
}
return null;
}

public static int ParseInt(string value, Func<string?> getPath)
{
try
{
return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
#endregion Core binding extensions.
}
}
Loading