未验证 提交 49369027 编写于 作者: R Rob Lindley 提交者: GitHub

Add ConfigurationKeyNameAttribute to binder and updated tests. (#50338)

上级 f33c4408
......@@ -15,6 +15,12 @@ public static partial class ConfigurationExtensions
public static string GetConnectionString(this Microsoft.Extensions.Configuration.IConfiguration configuration, string name) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationSection GetRequiredSection(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key) { throw null; }
}
[System.AttributeUsageAttribute(System.AttributeTargets.Property)]
public sealed partial class ConfigurationKeyNameAttribute : System.Attribute
{
public ConfigurationKeyNameAttribute(string name) { }
public string Name { get { throw null; } }
}
public static partial class ConfigurationPath
{
public static readonly string KeyDelimiter;
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
namespace Microsoft.Extensions.Configuration
{
[AttributeUsage(AttributeTargets.Property)]
public sealed class ConfigurationKeyNameAttribute : Attribute
{
public ConfigurationKeyNameAttribute(string name) => Name = name;
public string Name { get; }
}
}
......@@ -208,7 +208,7 @@ private static void BindProperty(PropertyInfo property, object instance, IConfig
return;
}
propertyValue = BindInstance(property.PropertyType, propertyValue, config.GetSection(property.Name), options);
propertyValue = GetPropertyValue(property, instance, config, options);
if (propertyValue != null && hasSetter)
{
......@@ -575,5 +575,48 @@ private static IEnumerable<PropertyInfo> GetAllProperties(Type type)
return allProperties;
}
private static object GetPropertyValue(PropertyInfo property, object instance, IConfiguration config, BinderOptions options)
{
string propertyName = GetPropertyName(property);
return BindInstance(
property.PropertyType,
property.GetValue(instance),
config.GetSection(propertyName),
options);
}
private static string GetPropertyName(MemberInfo property)
{
if (property == null)
{
throw new ArgumentNullException(nameof(property));
}
// Check for a custom property name used for configuration key binding
foreach (var attributeData in property.GetCustomAttributesData())
{
if (attributeData.AttributeType != typeof(ConfigurationKeyNameAttribute))
{
continue;
}
// Ensure ConfigurationKeyName constructor signature matches expectations
if (attributeData.ConstructorArguments.Count != 1)
{
break;
}
// Assumes ConfigurationKeyName constructor first arg is the string key name
string name = attributeData
.ConstructorArguments[0]
.Value?
.ToString();
return !string.IsNullOrWhiteSpace(name) ? name : property.Name;
}
return property.Name;
}
}
}
......@@ -34,6 +34,9 @@ public ComplexOptions()
internal string InternalProperty { get; set; }
protected string ProtectedProperty { get; set; }
[ConfigurationKeyName("Named_Property")]
public string NamedProperty { get; set; }
protected string ProtectedPrivateSet { get; private set; }
private string PrivateReadOnly { get; }
......@@ -201,6 +204,22 @@ public void CanBindIConfigurationSectionWithDerivedOptionsSection()
Assert.Null(options.Section.Value);
}
[Fact]
public void CanBindConfigurationKeyNameAttributes()
{
var dic = new Dictionary<string, string>
{
{"Named_Property", "Yo"},
};
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddInMemoryCollection(dic);
var config = configurationBuilder.Build();
var options = config.Get<ComplexOptions>();
Assert.Equal("Yo", options.NamedProperty);
}
[Fact]
public void EmptyStringIsNullable()
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册