Skip to content

Commit 00c60e4

Browse files
tarekgheerhardt
andauthored
Address ConfigurationBinder feedback (#81384)
Co-authored-by: Eric Erhardt <[email protected]>
1 parent 72978e1 commit 00c60e4

File tree

1 file changed

+30
-11
lines changed

1 file changed

+30
-11
lines changed

src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,16 @@ private static void BindInstance(
314314
return;
315315
}
316316

317-
// for sets and read-only set interfaces, we clone what's there into a new collection, if we can
317+
// -----------------------------------------------------------------------------------------------------------------------------
318+
// | bindingPoint | bindingPoint |
319+
// Interface | Value | IsReadOnly | Behavior
320+
// -----------------------------------------------------------------------------------------------------------------------------
321+
// ISet<T> | not null | true/false | Use the Value instance to populate the configuration
322+
// ISet<T> | null | false | Create HashSet<T> instance to populate the configuration
323+
// ISet<T> | null | true | nothing
324+
// IReadOnlySet<T> | null/not null | false | Create HashSet<T> instance, copy over existing values, and populate the configuration
325+
// IReadOnlySet<T> | null/not null | true | nothing
326+
// -----------------------------------------------------------------------------------------------------------------------------
318327
if (TypeIsASetInterface(type))
319328
{
320329
if (!bindingPoint.IsReadOnly || bindingPoint.Value is not null)
@@ -329,15 +338,25 @@ private static void BindInstance(
329338
return;
330339
}
331340

332-
// For other mutable interfaces like ICollection<>, IDictionary<,> and ISet<>, we prefer copying values and setting them
333-
// on a new instance of the interface over populating the existing instance implementing the interface.
334-
// This has already been done, so there's not need to check again.
335-
if (TypeIsADictionaryInterface(type) && !bindingPoint.IsReadOnly)
341+
// -----------------------------------------------------------------------------------------------------------------------------
342+
// | bindingPoint | bindingPoint |
343+
// Interface | Value | IsReadOnly | Behavior
344+
// -----------------------------------------------------------------------------------------------------------------------------
345+
// IDictionary<T> | not null | true/false | Use the Value instance to populate the configuration
346+
// IDictionary<T> | null | false | Create Dictionary<T> instance to populate the configuration
347+
// IDictionary<T> | null | true | nothing
348+
// IReadOnlyDictionary<T> | null/not null | false | Create Dictionary<K,V> instance, copy over existing values, and populate the configuration
349+
// IReadOnlyDictionary<T> | null/not null | true | nothing
350+
// -----------------------------------------------------------------------------------------------------------------------------
351+
if (TypeIsADictionaryInterface(type))
336352
{
337-
object? newValue = BindDictionaryInterface(bindingPoint.Value, type, config, options);
338-
if (newValue != null)
353+
if (!bindingPoint.IsReadOnly || bindingPoint.Value is not null)
339354
{
340-
bindingPoint.SetValue(newValue);
355+
object? newValue = BindDictionaryInterface(bindingPoint.Value, type, config, options);
356+
if (!bindingPoint.IsReadOnly && newValue != null)
357+
{
358+
bindingPoint.SetValue(newValue);
359+
}
341360
}
342361

343362
return;
@@ -538,7 +557,7 @@ private static bool CanBindToTheseConstructorParameters(ParameterInfo[] construc
538557
if (addMethod is null || source is null)
539558
{
540559
dictionaryType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
541-
var dictionary = Activator.CreateInstance(dictionaryType);
560+
object? dictionary = Activator.CreateInstance(dictionaryType);
542561
addMethod = dictionaryType.GetMethod("Add", DeclaredOnlyLookup);
543562

544563
var orig = source as IEnumerable;
@@ -748,9 +767,9 @@ private static Array BindArray(Type type, IEnumerable? source, IConfiguration co
748767
{
749768
Type elementType = type.GetGenericArguments()[0];
750769

751-
bool keyTypeIsEnum = elementType.IsEnum;
770+
bool elementTypeIsEnum = elementType.IsEnum;
752771

753-
if (elementType != typeof(string) && !keyTypeIsEnum)
772+
if (elementType != typeof(string) && !elementTypeIsEnum)
754773
{
755774
// We only support string and enum keys
756775
return null;

0 commit comments

Comments
 (0)