Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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 @@ -250,7 +250,7 @@ private static void BindProperties(object instance, IConfiguration configuration
continue;
}

if (constructorParameters is null || !constructorParameters.Any(p => p.Name == property.Name))
if (constructorParameters is null || !constructorParameters.Any(p => string.Equals(p.Name, property.Name, StringComparison.OrdinalIgnoreCase)))
{
BindProperty(property, instance, configuration, options);
Comment thread
tarekgh marked this conversation as resolved.
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public const bool NotSourceGenMode
= true;
#endif

public const bool SourceGenMode = !NotSourceGenMode;

public static IConfiguration GetConfigurationFromJsonString(string json)
{
var builder = new ConfigurationBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,30 @@ public string Value

public record RecordWithArrayParameter(string[] Array);

public class GetterOnlyCollectionWithCaseMismatchedCtorParameter
{
public GetterOnlyCollectionWithCaseMismatchedCtorParameter(List<string> instances) => Instances = instances;
public List<string> Instances { get; }
}

public class SettableCollectionWithCaseMismatchedCtorParameter
{
public SettableCollectionWithCaseMismatchedCtorParameter(List<string> instances) => Instances = instances;
public List<string> Instances { get; set; }
}

public class GetterOnlyInterfaceCollectionWithCaseMismatchedCtorParameter
{
public GetterOnlyInterfaceCollectionWithCaseMismatchedCtorParameter(IList<string> instances) => Instances = instances;
public IList<string> Instances { get; }
}

public class ParamsCollectionCtor
{
public ParamsCollectionCtor(params List<string> instances) => Instances = instances;
public List<string> Instances { get; }
}

public readonly record struct ReadonlyRecordStructTypeOptions(string Color, int Length);

public class ContainerWithNestedImmutableObject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1667,6 +1667,29 @@ public void CanBindOnParametersAndProperties_RecordWithArrayConstructorParameter
Assert.Equal(new string[] { "a", "b", "c" }, options.Array);
}

/// <summary>
/// When a constructor parameter name differs only by case from a matching collection property,
/// the binder must bind the collection once (through the constructor) and must not bind it again
/// through the property, which would otherwise duplicate the collection items.
/// </summary>
[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/83803", typeof(TestHelpers), nameof(TestHelpers.SourceGenMode))]
public void CanBindOnParametersAndProperties_GetterOnlyCollectionWithCaseMismatchedConstructorParameter()
{
string json = """
{
"Instances": [ "first", "second" ]
}
""";

IConfiguration config = TestHelpers.GetConfigurationFromJsonString(json);
string[] expected = new[] { "first", "second" };

Assert.Equal(expected, config.Get<GetterOnlyCollectionWithCaseMismatchedCtorParameter>().Instances);
Assert.Equal(expected, config.Get<SettableCollectionWithCaseMismatchedCtorParameter>().Instances);
Assert.Equal(expected, config.Get<GetterOnlyInterfaceCollectionWithCaseMismatchedCtorParameter>().Instances);
Assert.Equal(expected, config.Get<ParamsCollectionCtor>().Instances);
}

public static IEnumerable<object[]> Configuration_TestData()
{
Expand Down
Loading