ASP.net Core中的选项模式(Options Pattern)
分类: Asp.net Core入门 ◆ 标签: #Asp.Net core基础 #基础 #Web ◆ 发布于: 2023-06-04 20:26:19

我们上一节简要的介绍了应用如何访问存取配置,我们在存取配置时都是直接注入了IConfiguration
实例,然后通过该实例的方法来访问配置,但是最佳的做法实际上是通过选项模式来访问配置。
先快速的看一下如何什么是选项模式。
我们有一个配置文件如下:
"Position": { "Title": "Editor", "Name": "Joe Smith" }
定义一个选项类来表示这个这个配置:
public class PositionOptions { public const string Position = "Position"; public string Title { get; set; } public string Name { get; set; } }
对于选项类有如下的要求:
- 要么使用默认的构造函数,要么定义一个public的无参构造函数。
- 所有public的属性都要可读写.
- 字段不会被绑定。
存取方法
定义好了配置和定义好了选项类,可以使用如下几种方式来访问配置值:
使用ConfigurationBinder.bind
public class Test22Model : PageModel { private readonly IConfiguration Configuration; public Test22Model(IConfiguration configuration) { Configuration = configuration; } public ContentResult OnGet() { var positionOptions = new PositionOptions(); Configuration.GetSection(PositionOptions.Position).Bind(positionOptions); return Content($"Title: {positionOptions.Title} \n" + $"Name: {positionOptions.Name}"); } }
使用`ConfigurationBinder.Get
public class Test21Model : PageModel { private readonly IConfiguration Configuration; public PositionOptions positionOptions { get; private set; } public Test21Model(IConfiguration configuration) { Configuration = configuration; } public ContentResult OnGet() { positionOptions = Configuration.GetSection(PositionOptions.Position) .Get<PositionOptions>(); return Content($"Title: {positionOptions.Title} \n" + $"Name: {positionOptions.Name}"); } }
使用DI注入
我们先在方法ConfigureService
中配置配置:
public void ConfigureServices(IServiceCollection services) { services.Configure<PositionOptions>(Configuration.GetSection( PositionOptions.Position)); services.AddRazorPages(); }
在DI系统中配置好了之后,可以使用如下几种接口来访问:
使用IOptions<T>
public class Test2Model : PageModel { private readonly PositionOptions _options; public Test2Model(IOptions<PositionOptions> options) { _options = options.Value; } public ContentResult OnGet() { return Content($"Title: {_options.Title} \n" + $"Name: {_options.Name}"); } }
Tips
使用IOptions<T>
, 无法在更改了配置文件之后,重新读入配置,因为IOptions<T>
被注册为Singleton服务。
使用IOptionSnapshot<T>
访问
public class TestSnapModel : PageModel { private readonly MyOptions _snapshotOptions; public TestSnapModel(IOptionsSnapshot<MyOptions> snapshotOptionsAccessor) { _snapshotOptions = snapshotOptionsAccessor.Value; } public ContentResult OnGet() { return Content($"Option1: {_snapshotOptions.Option1} \n" + $"Option2: {_snapshotOptions.Option2}"); } }
tips
注意IOptionSnapshot<T>
可以即时监控配置文件的变化,因为它是scope范围的。
使用IOptionsMonitor
public class TestMonitorModel : PageModel { private readonly IOptionsMonitor<MyOptions> _optionsDelegate; public TestMonitorModel(IOptionsMonitor<MyOptions> optionsDelegate ) { _optionsDelegate = optionsDelegate; } public ContentResult OnGet() { return Content($"Option1: {_optionsDelegate.CurrentValue.Option1} \n" + $"Option2: {_optionsDelegate.CurrentValue.Option2}"); } }
也是可以感知配置文件变化,同时支持命名选项。
什么是命名选项
当不同的配置节有使用到相同的属性名,就需要使用命名选项来区分,看下面的例子:
{ "TopItem": { "Month": { "Name": "Green Widget", "Model": "GW46" }, "Year": { "Name": "Orange Gadget", "Model": "OG35" } } }
TopItem:Month
和TopItem:Year
中有相同的属性,Name和Model
我们可以这样类配置类:
public class TopItemSettings { public const string Month = "Month"; public const string Year = "Year"; public string Name { get; set; } public string Model { get; set; } }
配置DI容器:
public void ConfigureServices(IServiceCollection services) { services.Configure<TopItemSettings>(TopItemSettings.Month, Configuration.GetSection("TopItem:Month")); services.Configure<TopItemSettings>(TopItemSettings.Year, Configuration.GetSection("TopItem:Year")); services.AddRazorPages(); }
然后使用如下的代码进行存取:
public class TestNOModel : PageModel { private readonly TopItemSettings _monthTopItem; private readonly TopItemSettings _yearTopItem; public TestNOModel(IOptionsSnapshot<TopItemSettings> namedOptionsAccessor) { _monthTopItem = namedOptionsAccessor.Get(TopItemSettings.Month); _yearTopItem = namedOptionsAccessor.Get(TopItemSettings.Year); } public ContentResult OnGet() { return Content($"Month:Name {_monthTopItem.Name} \n" + $"Month:Model {_monthTopItem.Model} \n\n" + $"Year:Name {_yearTopItem.Name} \n" + $"Year:Model {_yearTopItem.Model} \n" ); } }
这里就是命名选项的用法。
Tips
默认情况下,ASP.net Core是感知配置文件的变化的。