ASP.NET Core 8 Blazor中IOptions模式配置注入实现是否符合最佳实践?
关于Blazor中配置映射实现的最佳实践咨询
我正在学习.NET Core(Blazor),了解到有多种方式让组件获取appsettings.json中的配置。我倾向于通过类映射配置根节点的方式,因此尝试实现IOptions模式。当前使用Visual Studio 17.10.4、ASP.NET Core 8及对应SDK,代码可正常运行,但想咨询此实现方式是否恰当,是否需要调整及原因。
我的代码
AppOptions.cs
using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Licensing.Shared { public class AppOptions { public Components Components { get; set; } = new Components(); } public class Components { public Pages Pages { get; set; } = new Pages(); } public class Pages { public Table Table { get; set; } = new Table(); } public class Table { public int PageSize { get; set; } = default; public List<int>? PageSizeOptions { get; set; } = []; } }
Program.cs
using Licensing.Components; using Radzen; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Licensing.Data; using Licensing.Components.Utils; using Licensing.Shared; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContextFactory<LicensingContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("LicensingContext") ?? throw new InvalidOperationException("Connection string 'LicensingContext' not found."))); //builder.Services.AddQuickGridEntityFrameworkAdapter(); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); // Add Razor builder.Services.AddRadzenComponents(); // Add my Event Console builder.Services.AddScoped<EventConsole>(); // --------THIS-------- // This is a singleton (static) service where the scope exists across the app (all settings will not change in appsettings.json at run-time). builder.Services.AddSingleton<AppOptions>(builder.Configuration.GetSection("AppSettings").Get<AppOptions>()); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error", createScopeForErrors: true); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); app.UseMigrationsEndPoint(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseAntiforgery(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode(); app.Run();
appsettings.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "LicensingContext": "Server=(localdb)\\mssqllocaldb;Database=LicensingContext-5acfd89b-2b0c-4df3-a82f-719fdcde315b;Trusted_Connection=True;MultipleActiveResultSets=true" }, "AppSettings": { "Components": { "Pages": { "Table": { "PageSize": 6, "PageSizeOptions": [ 4, 6, 10, 30 ] } } } } }
最佳实践分析与调整建议
1. 当前实现的合理性
你的代码是可行且合理的:
- 由于明确配置在运行时不会修改,将
AppOptions注册为单例(Singleton)是合适的,避免重复解析配置,提升性能。 - 配置类的层级结构与
appsettings.json中的AppSettings节点完全对应,组织清晰,便于维护和理解。
2. 符合官方最佳实践的优化方向
虽然当前实现可用,但更推荐使用ASP.NET Core官方的IOptions<T>模式,原因如下:
- 规范性与生态一致性:
IOptions<T>是官方推荐的配置注入方式,团队协作时更容易统一认知,与框架其他组件的使用方式保持一致。 - 扩展性更强:后续如果需要支持配置热重载(即使现在不需要,预留扩展空间),可以无缝切换到
IOptionsSnapshot<T>或IOptionsMonitor<T>,而无需修改依赖注入的消费端代码。 - 支持配置验证:结合
Microsoft.Extensions.Options.DataAnnotations包,可轻松给配置类添加数据验证规则(比如限制PageSize的取值范围),确保配置的合法性。
修改方式:
在Program.cs中将原注册代码替换为:
builder.Services.Configure<AppOptions>(builder.Configuration.GetSection("AppSettings"));
在组件或服务中通过注入IOptions<AppOptions>来获取配置:
private readonly AppOptions _appOptions; public YourComponent(IOptions<AppOptions> appOptions) { _appOptions = appOptions.Value; }
3. 配置类的精简优化
- 移除无用引用:
AppOptions.cs中的using Microsoft.CodeAnalysis.CSharp.Syntax;没有实际作用,建议删除,减少代码冗余。 - 调整可空类型:
PageSizeOptions已经初始化了空列表,无需声明为List<int>?,改为List<int>即可,避免后续使用时的空值检查。 - 可选:添加
[Options]特性(需安装Microsoft.Extensions.Options.DataAnnotations包),为后续配置验证做准备:
using Microsoft.Extensions.Options; namespace Licensing.Shared { [Options] public class AppOptions { public Components Components { get; set; } = new Components(); } // 其他类保持不变... }
内容的提问来源于stack exchange,提问作者user7990543
相关产品推荐
相关产品推荐

