我可以在ASP中进行必要的配置吗?网络核心?



下面是我的启动代码:

services.Configure<FooBarOptions>(Configuration.GetSection("FooBarOptions"));

这是一个错误,因为我想

services.Configure<FooBarOptions>(Configuration.GetSection("FooBar"));

很明显,这个错别字导致配置没有被加载。当所需的配置部分不存在时,是否有一种方法可以在启动期间触发错误?

使用带有回调的PostConfigure<T>,该回调将在每个Configure<T>执行后运行。这将允许用户以任何方式以任何顺序配置一个选项,并允许您查看(un)配置的选项,并在需要时抛出异常。

class FooBarOptions
{
public string AString { get; set; }
}
services.PostConfigure<FooBarOptions>(options => {
// ... validate configuration
if (options.AString == null)
{
throw new InvalidProgramException($"{nameof(FooBarOptions)} is not configured properly");
}
});
services.Configure<FooBarOptions>(Configuration.GetSection("FooBarOptions"));
引用

  • https://learn.microsoft.com/en us/aspnet/core/fundamentals/configuration/options?view=aspnetcore - 5.0 # options-post-configuration
  • https://andrewlock.net/delaying-strongly-typed-options-configuration-using-postconfigure-in-asp-net-core/

如果你想保留" binding ";部分的启动文件有点简洁,IConfigurationIServiceCollection上的扩展方法都可以工作。下面是一个基本的实现。

static class ConfigurationBindingExtensions
{
public static void BindSection<T>(this IConfiguration configuration, IServiceCollection services, string sectionName) where T : class
{
var config = configuration.GetSection(sectionName);
if (config.Exists())
{
services.Configure<T>(config);
}
else
{
throw new ConfigurationSectionNotFoundException(sectionName);
}
}
}
[Serializable]
class ConfigurationSectionNotFoundException : Exception, System.Runtime.Serialization.ISerializable
{
public string SectionName { get; set; }
public ConfigurationSectionNotFoundException(string sectionName)
: this(sectionName, string.Format("Section {0} was not found in the configuration file", sectionName))
{
this.SectionName = sectionName;
}
public ConfigurationSectionNotFoundException(string sectionName, string message)
: base(message)
{
this.SectionName = sectionName;
}
protected ConfigurationSectionNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
: base(info, context)
{
if (info == null)
throw new ArgumentNullException(nameof(info));
SectionName = info.GetString("SectionName");
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter = true)]
public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
if (info == null)
throw new ArgumentNullException(nameof(info));
info.AddValue("SectionName", SectionName);
base.GetObjectData(info, context);
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand, Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)]
void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
if (info == null)
throw new ArgumentNullException(nameof(info));
GetObjectData(info, context);
}
}

你可以这样调用它:

Configuration.BindSection<FooBarOptions>(services, "FooBar");

如果section没有定义,这将抛出一个自定义异常——如果对你更有意义,你可以用其他东西替换它。可能有点过头了,但它能让Startup.cs保持整洁。

try this

var exist = Configuration.GetSection("FooBar").Exist();
if (exist) services.Configure<FooBarOptions>(Configuration.GetSection("FooBar"));
else ....throw exception

最新更新