Skip to content

ConfigurationBinder fails to set values for properties of a type with ISet<T> variations #66141

@xakep139

Description

@xakep139

Description

ConfigurationBinder throws an exception in curtain cases related to ISet<T> usages.
Exception message is:

Object of type 'System.Collections.Generic.List`1[System.String]' cannot be converted to type 'System.Collections.Generic.ISet`1[System.String]'.

So far I found these cases:

class MyOptions
{
    public ISet<string>? Prop1 { get; set; }

    public IDictionary<string, ISet<string>> Prop2 { get; set; } = new Dictionary<string, ISet<string>>();

    public IDictionary<string, ISet<string>>? Prop3 { get; set; }
}

Reproduction Steps

I created a short repro: https://github.com/xakep139/config-binder-set-issue
In MyOptions class all properties that cause an exception are commented out, i.e.:

  • public ISet<string>? NullableSet { get; set; }
  • public IDictionary<string, ISet<string>> AssignedISetDict { get; set; } = new Dictionary<string, ISet<string>>();
  • public IDictionary<string, ISet<string>>? NullableISetDict { get; set; }

Expected behavior

No exception is thrown, values are bound as expected

Actual behavior

The exception is thrown:

System.ArgumentException
  HResult=0x80070057
  Message=Object of type 'System.Collections.Generic.List`1[System.String]' cannot be converted to type 'System.Collections.Generic.ISet`1[System.String]'.
  Source=System.Private.CoreLib
  StackTrace:
   at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast) in /_/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs:line 3596
   at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr) in /_/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs:line 3557
   at System.Reflection.MethodBase.CheckArguments(StackAllocedArguments& stackArgs, ReadOnlySpan`1 parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig) in /_/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs:line 99
   at System.Reflection.RuntimeMethodInfo.InvokeOneParameter(Object obj, BindingFlags invokeAttr, Binder binder, Object parameter, CultureInfo culture) in /_/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs:line 469
   at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture) in /_/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs:line 382
   at System.Reflection.PropertyInfo.SetValue(Object obj, Object value) in /_/src/libraries/System.Private.CoreLib/src/System/Reflection/PropertyInfo.cs:line 52
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindProperty(PropertyInfo property, Object instance, IConfiguration config, BinderOptions options) in /_/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs:line 267
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindNonScalar(IConfiguration configuration, Object instance, BinderOptions options) in /_/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs:line 233
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, Object instance, IConfiguration config, BinderOptions options) in /_/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs:line 406
   at Microsoft.Extensions.Configuration.ConfigurationBinder.Bind(IConfiguration configuration, Object instance, Action`1 configureOptions) in /_/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs:line 137
   at Microsoft.Extensions.Options.NamedConfigureFromConfigurationOptions`1.BindFromOptions(TOptions options, IConfiguration config, Action`1 configureBinder) in /_/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/NamedConfigureFromConfigurationOptions.cs:line 46
   at Microsoft.Extensions.Options.NamedConfigureFromConfigurationOptions`1.<>c__DisplayClass1_0.<.ctor>b__0(TOptions options) in /_/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/NamedConfigureFromConfigurationOptions.cs:line 36
   at Microsoft.Extensions.Options.ConfigureNamedOptions`1.Configure(String name, TOptions options) in /_/src/libraries/Microsoft.Extensions.Options/src/ConfigureNamedOptions.cs:line 52
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name) in /_/src/libraries/Microsoft.Extensions.Options/src/OptionsFactory.cs:line 87
   at Microsoft.Extensions.Options.UnnamedOptionsManager`1.get_Value() in /_/src/libraries/Microsoft.Extensions.Options/src/UnnamedOptionsManager.cs:line 30
   at ConsoleApp1.Program.<Main>d__0.MoveNext() in C:\Users\nbalabaev\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 21
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/ExceptionServices/ExceptionDispatchInfo.cs:line 56
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs:line 181
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs:line 149
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult() in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs:line 104
   at ConsoleApp1.Program.<Main>(String[] args)

Regression?

No response

Known Workarounds

As a workaround you can:

  • assign a HashSet<T> to a property or
  • provide a HashSet<T> as a TValue for IDictionary<TKey, TValue>

Configuration

Runtime version is net6.0, SDK version is 6.0.200
Windows 11 Enterprise 21H2 (OS build 22000.493)

Other information

I guess the label should be area-Extensions-Configuration

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions