Skip to content

ConfigurationBinder doesn't honor pre-existing ISet when binding #79766

Closed
@ericstj

Description

@ericstj

Description

When binding to a property that exposes an ISet with a setter and initializes the property with some collection, that collection is ignored and instead a new HashTable is created. This could change the comparator or otherwise result in different behavior than the pre-allocated collection.

Reproduction Steps

using Configuration.Binder.Working;
using Microsoft.Extensions.Configuration;


IConfiguration config = new ConfigurationBuilder()
    .AddInMemoryCollection()
    .Build();

config["MySet:0"] = "HelloWorld";
TestObject obj = config.Get<TestObject>()!;

Console.WriteLine($"Test object contains helloworld: {obj.MySet.Contains("helloworld")}");

// workaround
obj.MySet = new HashSet<string>(obj.MySet, StringComparer.OrdinalIgnoreCase);
Console.WriteLine($"Test object contains helloworld: {obj.MySet.Contains("helloworld")}");

public class TestObject
{
    public ISet<string> MySet { get; set; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
}

Expected behavior

This should succeed, using the user-initialized collection with case insensitive comparer.

Actual behavior

The first call fails because ConfigurationBinder recreated the ISet<string> as a new HashSet<string>() using case-sensitive comparer.

Regression?

Yes, from 6.0.0 due to this PR #68133

Known Workarounds

One can recreate the collection after binding.

obj.MySet = new HashSet<string>(obj.MySet, StringComparer.OrdinalIgnoreCase);

Or hide the setter, to prevent ConfigurationBinder from resetting the instance.

Configuration

No response

Other information

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions