5.该类的字段不会被绑定
"Blog": { "Title": "ASP.NET Core Options", "Content": "This is a blog about Options System in ASP.NET Core Framework.", "CreateTime": "2022-12-06" }之后定义一个选项类:
public class BlogOptions { public const string Blog = "Blog"; public string Title { get; set; } public string Content { get; set; } public DateTime CreateTime { get; set; } }然后,在任何可以获取到 IConfiguration 服务的地方都可以通过 IConfiguration 服务进行绑定:
using OptionsSample.Options; using System.Text.Json; var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); var blog1 = new BlogOptions(); app.Configuration.GetSection(BlogOptions.Blog).Bind(blog1); var blog2 = app.Configuration.GetSection(BlogOptions.Blog).Get<BlogOptions>(); Console.WriteLine(JsonSerializer.Serialize(blog1)); Console.WriteLine(JsonSerializer.Serialize(blog2)); app.Run();
// 通过配置文件读取某一配置节点 //builder.Services.Configure<BlogOptions>(builder.Configuration.GetSection(BlogOptions.Blog));这里通过获取特定的配置节点,并将其配置为选项,之后就可以在任何能够进行依赖注入的地方使用注入的 BlogOptions 选项类了。
var blogOption = app.Services.GetRequiredService<IOptions<BlogOptions>>().Value; Console.WriteLine(JsonSerializer.Serialize(blogOption));这里使用到的 Configure 方法是 OptionsConfigurationServiceCollectionExtensions 类中的扩展方法,选项系统中有好几个同名的 Configure 方法,但是这些是并不是同一个方法的重载,下面会详细讲到。
//硬编码的方式设置配置信息,也可以在这里读取数据库信息 builder.Services.Configure<BlogOptions>(option => { option.Title = "test"; option.Content = "test hard code option"; option.CreateTime = DateTime.Now; });这种情况用得不多,在这种情况下我们可以进行额外的一些逻辑,例如从数据库中获取一些信息。这里的 Configure 方法是 OptionsServiceCollectionExtensions 扩展类中的方法。值得注意的是,在同时使用上面两个方法配置同一个选项类的情况下,硬编码配置的方式优先。
builder.Services.AddOptions<BlogOptions>() // 这里可以通过 Configure 方法指定需要的服务, IServiceProvider 只是一个示例 .Configure<IServiceProvider>((option, service) => // 接收的的第一个参数选项类对象,后面依次是所注入的服务 { // 通过注入的服务执行相应的逻辑 option.Title = "test DI Configure"; option.Content = "test DI Configure"; option.CreateTime = DateTime.Now; });这里的 Configure 方法,与上面的不一样,不再是 IServiceCollection 的扩展方法,而是 OptionsBuilder 类中的方法,AddOptions 扩展方法在 OptionsServiceCollectionExtensions 中,返回一个 OptionsBuilder 对象。该方法有多个重载,最多支持5个服务来配置选项:
"FirstBlog": { "Title": "ASP.NET Core Options", "Content": "This is a blog about Options System in ASP.NET Core Framework.", "CreateTime": "2022-12-06" }, "SecondBlog": { "Title": "ASP.NET Core Configuration", "Content": "This is a blog about Configuration System in ASP.NET Core Framework.", "CreateTime": "2022-12-08" }这种情况下,两个配置节点其实可以用同一个选项类接收,它们的结构是一样的。而命名选项就是为了应对这种情况,选项系统中允许为当前配置的选项命名,而选项系统区分同一个类型的不同选项也是根据名字进行区分的。事实上,.NET Core 中所有 Options 都是命名选项,当没有显式指定名字时(如上面讲到的默认配置方式),使用的名字默认是Options.DefaultName,即string.Empty。
//堆代码 duidaima.com builder.Services.Configure<BlogOptions>("First", builder.Configuration.GetSection("FirstBlog")); builder.Services.Configure<BlogOptions>("Second", builder.Configuration.GetSection("SecondBlog"));这里要说明的是,上面我们从依赖注入容器中解析 IOptions 接口,从而获取我们需要的选项值,但是使用命名选项的情况下是无法通过 IOptions 接口解析相应的选项的,必须通过 IOptionsMonitor 或者 IOptionsSnapshot 接口来解析。这三个接口的区别下面会重点讲。
var blog = app.Services.GetRequiredService<IOptions<BlogOptions>>().Value; Console.WriteLine(JsonSerializer.Serialize(blog)); var firstBlog = app.Services.GetRequiredService<IOptionsMonitor<BlogOptions>>().Get("First"); Console.WriteLine(JsonSerializer.Serialize(firstBlog)); var secondBlog = app.Services.GetRequiredService<IOptionsMonitor<BlogOptions>>().Get("Second"); Console.WriteLine(JsonSerializer.Serialize(secondBlog));2.2.4 后期配置
builder.Services.Configure<BlogOptions>("First", builder.Configuration.GetSection("FirstBlog")); builder.Services.PostConfigure<BlogOptions>("First", options => { options.Title = "Post Config"; }); var firstBlog = app.Services.GetRequiredService<IOptionsMonitor<BlogOptions>>().Get("First"); Console.WriteLine(JsonSerializer.Serialize(firstBlog));除了 PostConfigure 方法外,还有 PostConfigureAll 方法,前者对单一选项类单一命名的选项对象进行后期配置,如果没有指定名称则是默认名称,后者会对统一选项类下的不同命名选项统一进行配置。
// 堆代码 duidaima.com builder.Services.Configure<BlogOptions>("First", builder.Configuration.GetSection("FirstBlog")); builder.Services.Configure<BlogOptions>("Second", builder.Configuration.GetSection("SecondBlog")); builder.Services.PostConfigureAll<BlogOptions>(options => { options.Title = "Post Config"; }); var firstBlog = app.Services.GetRequiredService<IOptionsMonitor<BlogOptions>>().Get("First"); Console.WriteLine(JsonSerializer.Serialize(firstBlog)); var secondBlog = app.Services.GetRequiredService<IOptionsMonitor<BlogOptions>>().Get("Second"); Console.WriteLine(JsonSerializer.Serialize(secondBlog));通过 IOptionsMonitor 或者 IOptionsSnapshot 接口解析选项,在配置来源更改的情况下,相应的选项内容也会随之变化(两者的适用场景不同), 后期配置逻辑在选项的每一次更改之后都会执行。