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
Next Next commit
Allow ConfigBinder to bind arrays to Singular elements
When trying to bind a collection of type `T`, ConfigBinder will now try
to bind to the current object instead of children objects when the
provided configuration doesn't contain an array.

This change allows elements that are not arrays to be bound to arrays.
For example, a type string[] can now be bound to "key" along with
"key:0".
  • Loading branch information
vidommet committed Aug 11, 2021
commit beb621a84f5a5f5d62bd91d880f6ade7066e17d5
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ private static object BindInstance(
return convertedValue;
}

if (config != null && config.GetChildren().Any())
if (config != null && (config.GetChildren().Any() || configValue != null))
{
// If we don't have an instance, try to create one
if (instance == null)
Expand Down Expand Up @@ -495,7 +495,17 @@ private static void BindCollection(
Type itemType = collectionType.GenericTypeArguments[0];
MethodInfo addMethod = collectionType.GetMethod("Add", DeclaredOnlyLookup);

foreach (IConfigurationSection section in config.GetChildren())
IEnumerable<IConfigurationSection> children;
if (config.GetChildren().Any(a => long.TryParse(a.Key, out _)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we extract this into a helper method and use it in both places? Also it would be nice to write a comment or two about what this is doing, and why.

{
children = config.GetChildren();
}
else
{
children = new[] { config as IConfigurationSection };
}

foreach (IConfigurationSection section in children)
{
try
{
Expand All @@ -518,7 +528,16 @@ private static void BindCollection(
[RequiresUnreferencedCode("Cannot statically analyze what the element type is of the Array so its members may be trimmed.")]
private static Array BindArray(Array source, IConfiguration config, BinderOptions options)
{
IConfigurationSection[] children = config.GetChildren().ToArray();
IConfigurationSection[] children;
if (config.GetChildren().Any(a => long.TryParse(a.Key, out _)))
{
children = config.GetChildren().ToArray();
}
else
{
children = new[] { config as IConfigurationSection };
}

int arrayLength = source.Length;
Type elementType = source.GetType().GetElementType();
var newArray = Array.CreateInstance(elementType, arrayLength + children.Length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,34 @@ public void ExceptionWhenTryingToBindToByteArray()
exception.Message);
}

[Fact]
public void CanBindSingleElementToCollection()
{
var dic = new Dictionary<string, string>
{
{"MyString", "hello world"},
{"Nested:Integer", "11"},
};

var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddInMemoryCollection(dic);
var config = configurationBuilder.Build();

var stringArr = config.GetSection("MyString").Get<string[]>();
Assert.Equal("hello world", stringArr[0]);
Assert.Equal(1, stringArr.Length);

var stringAsStr = config.GetSection("MyString").Get<string>();
Assert.Equal("hello world", stringAsStr);

var nested = config.GetSection("Nested").Get<NestedOptions>();
Assert.Equal(11, nested.Integer);

var nestedAsArray = config.GetSection("Nested").Get<NestedOptions[]>();
Assert.Equal(11, nestedAsArray[0].Integer);
Assert.Equal(1, nestedAsArray.Length);
}

private interface ISomeInterface
{
}
Expand Down