【发布时间】:2020-08-10 09:24:33
【问题描述】:
我正在尝试使用 ASP.NET Core 3.1 和选项模式在 C# 中编写扩展方法,该方法可以绑定提供程序中提供的任何现有配置(例如 appsettings.json),或者如果没有找到现有配置则绑定改为配置的默认对象。
我的目标是允许开发人员选择在 appsettings.json 中包含他们自己的自定义配置,或者只使用默认选项。
我遇到的问题是,当我尝试将对象SomeOptions 绑定到配置对象,然后尝试通过调用Configuration.GetSection("SomeOptions").Get<SomeOptions>() 检索IOptions<SomeOptions> 时,它总是返回一个空对象。
例如:
// Binding the creating options object to the configuration
var someOptions = new SomeOptions();
var section = Configuration.GetSection("SomeOptions")
section.Bind(someOptions);
// Retrieve the IOptions<SomeOptions> from the configuration
// This is the problem - it always returns null
var retrievedOptions = section.Get<SomeOptions>();
为什么新创建的对象没有绑定到配置?
这是我写的函数:
/// <summary>
/// Adds options to the <see cref="IServiceCollection"/> injected services.
/// If no options can be found within configuration then the default options will be used.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add the option bindings to.</param>
/// <param name="configuration">The <see cref="IConfiguration"/> object used to retrieve the configuration sections from.</param>
/// <param name="sectionName">
/// The name of the configuration section to bind the options with.
/// If the configuration section cannot be found or it's blank the default configuration will be used instead.
/// </param>
/// <returns>The originally passed <see cref="IServiceCollection"/> with the added options.</returns>
public static IServiceCollection AddTransientOptionsWithDefault<TOptions>(this IServiceCollection services, IConfiguration configuration, string sectionName)
where TOptions : class, new()
{
if (configuration == null)
{
throw new ArgumentNullException(nameof(configuration));
}
// Retrieve any configured options
var section = configuration.GetSection(sectionName);
// If no configuration was found use the default options
var options = section.Get<TOptions>();
if (options == null)
{
options = new TOptions();
// This section here seems to be the issue.
// These are all of the different binding methods I've tried.
section.Bind(options);
//configuration.GetSection(sectionName).Bind(options);
//services.Configure<TOptions>(configureOptions => new TOptions());
//configuration.Bind(options);
}
// This returns null as it can't find the added TOptions
var newSection = configuration.GetSection(sectionName).Get<TOptions>();
// Another example - this returns an empty list
var sectionChildren = section.GetChildren();
services.Configure<TOptions>(section);
return services;
}
示例选项对象:
public class CorsOptions
{
public string[] Origins { get; set; } = Array.Empty<string>();
}
appsettings.json:
{
"Cors": {
"Origins": [ "www.google.com" ]
}
}
以上所有内容在现实世界中的使用示例...
Startup.cs sn-p:
private IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
AddCorsWithOrigins(services, Configuration);
}
private IServiceCollection AddCorsWithOrigins(IServiceCollection services, IConfiguration configuration)
{
// The idea here is that any "Cors" configuration will be used if it exists,
// otherwise it will just add the default IOptions<CorsOptions> instead
services.AddTransientOptionsWithDefault<CorsOptions>(configuration, "Cors");
// Retrieve the options that have been added to the configuration
var corsOptions = configuration.GetSection("Cors");
// Do something with the corsOptions object that has been added...
}
【问题讨论】:
-
I'm able to unable to bind a newly created object to the IServices/IConfiguration object to be later retrieved through a standard Configuration.GetSection("SomeName").Get()能否进一步说明问题? -
我已经用一个更好的问题示例更新了这个问题
-
我们可以查看您的默认 SomeOptions 实例吗?你在哪里设置它的默认值?
-
我添加了更详细的配置、选项以及如何在实际解决方案中发挥作用的更好示例。
-
嗨。只是一个善意的提醒。在这种情况下仍然没有公认的答案,你需要别的吗?
标签: c# asp.net-core asp.net-core-3.1