Skip to content

Commit

Permalink
ConfigurationBinder.Bind on virtual properties duplicates elements (#…
Browse files Browse the repository at this point in the history
…70592)

* ConfigurationBinder.Bind on virtual properties duplicates elements

* simplify GetAllProperties

* return array instead of list
  • Loading branch information
pedrobsaila authored Jun 14, 2022
1 parent 978df67 commit 0ca092e
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public static void Bind(this IConfiguration configuration, object? instance, Act
[RequiresUnreferencedCode(PropertyTrimmingWarningMessage)]
private static void BindNonScalar(this IConfiguration configuration, object instance, BinderOptions options)
{
List<PropertyInfo> modelProperties = GetAllProperties(instance.GetType());
PropertyInfo[] modelProperties = GetAllProperties(instance.GetType());

if (options.ErrorOnUnknownConfiguration)
{
Expand Down Expand Up @@ -451,7 +451,7 @@ private static object CreateInstance(
}


List<PropertyInfo> properties = GetAllProperties(type);
PropertyInfo[] properties = GetAllProperties(type);

if (!DoAllParametersHaveEquivalentProperties(parameters, properties, out string nameOfInvalidParameters))
{
Expand Down Expand Up @@ -482,7 +482,7 @@ private static object CreateInstance(
}

private static bool DoAllParametersHaveEquivalentProperties(ParameterInfo[] parameters,
List<PropertyInfo> properties, out string missing)
PropertyInfo[] properties, out string missing)
{
HashSet<string> propertyNames = new(StringComparer.OrdinalIgnoreCase);
foreach (PropertyInfo prop in properties)
Expand Down Expand Up @@ -752,22 +752,8 @@ private static bool IsArrayCompatibleReadOnlyInterface(Type type)
return null;
}

private static List<PropertyInfo> GetAllProperties(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
Type type)
{
var allProperties = new List<PropertyInfo>();

Type? baseType = type;
do
{
allProperties.AddRange(baseType!.GetProperties(DeclaredOnlyLookup));
baseType = baseType.BaseType;
}
while (baseType != typeof(object));

return allProperties;
}
private static PropertyInfo[] GetAllProperties([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type)
=> type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);

[RequiresUnreferencedCode(PropertyTrimmingWarningMessage)]
private static object? BindParameter(ParameterInfo parameter, Type type, IConfiguration config,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1750,6 +1750,21 @@ public void CanBindNullableNestedStructProperties()
Assert.True(bound.NullableNestedStruct.Value.DeeplyNested.Boolean);
}

[Fact]
public void CanBindVirtualPropertiesWithoutDuplicates()
{
ConfigurationBuilder configurationBuilder = new();
configurationBuilder.AddInMemoryCollection(new Dictionary<string, string>
{
{ "Test:0", "1" }
});
IConfiguration config = configurationBuilder.Build();

var test = new ClassOverridingVirtualProperty();
config.Bind(test);
Assert.Equal("1", Assert.Single(test.Test));
}


private interface ISomeInterface
{
Expand Down Expand Up @@ -1827,5 +1842,15 @@ public struct DeeplyNested
public bool Boolean { get; set; }
}
}

public class BaseClassWithVirtualProperty
{
public virtual string[] Test { get; set; } = System.Array.Empty<string>();
}

public class ClassOverridingVirtualProperty : BaseClassWithVirtualProperty
{
public override string[] Test { get => base.Test; set => base.Test = value; }
}
}
}

0 comments on commit 0ca092e

Please sign in to comment.