当前位置: 首页 > news >正文

.NET8 通过自定义类映射appsettings.json 文件某个节点的配置

目的:在Program 初始化时,希望可以读取 appsettings.json 配置文件的某个节点的内容,自动映射到自定义类中,以便其他消费者进行注入使用配置的属性和值;

步骤1:例如 appsettings.json 配置如下:

{ 
"Settings": { 
"ApiUrl": "<https://wms.api.example.com>", 
"Code": "PROG001" } 
}

步骤2:创建一个自定义类,ServiceOptions

     public class ServiceOptions{ public string ApiUrl { get; set; } public string Code { get; set; }}

该类的属性,必须和 appsettings.json 文件中,Settings 节点的属性相同

步骤3在 Program.cs 中注册服务到 DI 容器

    builder.Services.Configure<ServiceOptions>(builder.Configuration.GetSection("Settings"));

最后:在需要使用的地方,进行自动注入;例如,当前在一个Controller 中去使用配置

    public class SomeController : ControllerBase {private readonly ServiceOptions _serviceOptions;public SomeController(ServiceOptions service){_serviceOptions = service;}}

如果在Program.cs 中注册的自定义配置类,但是由于其他一些服务的注册生命周期和自定义配置类的不同(默认scoped),导致服务无法解析,出现注册失败的情况。
解决方法:把消费者类构造函数改为接收 IOptionsMonitor<T>或 IOptions<T>)如下:

    public class SomeController : ControllerBase {private readonly ServiceOptions _serviceOptions;public SomeController(IOptionsMonitor<ServiceOptions> service){_serviceOptions = service?.CurrentValue;// 如果需要在配置变更时更新内部状态,可订阅:service.OnChange(newOpts => {// 更新 _options 或执行必要逻辑(注意并发)_serviceOptions = newOpts;});}}

or

    public class SomeController : ControllerBase {private readonly ServiceOptions _serviceOptions;public SomeController(IOptions<ServiceOptions> service){_serviceOptions = service.Value;}}
  1. 无论使用IOptions,或者是 IOptionsMonitor,都是直接使用_serviceOptions.Code 来直接访问相关属性
  2. 使用优先级
    • 如果配置在运行时需要动态更新并且希望服务能感知这些变化,优先使用 IOptionsMonitor<T>。原因:IOptionsMonitor<T> 提供 CurrentValue 并能通过 OnChange 订阅配置变更,适合运行期需要热更新的场景。
    • 如果配置在启动时读取一次即可且不会变化,使用 IOptions 更简单一些。原因:IOptions<T> 在注入时返回一个固定的快照(startup value),适合只读一次的场景。
    • 绝不要用 IOptionsSnapshot 注入到单例(它是 scoped,只能被 scoped/transient 消费)

另外一种使用情况:如果想 在 Program.cs 初始化时,也需要在 Program.cs 中临时使用 appsettings.json 节点的一些属性的值。

步骤一:除了可以通过 builder.Configuration["Settings:ApiUrl"] 这种方式简单获取,还可以继续使用上面的方式,映射到自定义的类中去获取相关的属性和值,

获取方式一:在 Program.cs 中,配置

    ServiceOptions options = builder.Configuration.GetSection("Settings").Get<ServiceOptions>();

通过 options.Code 这样便能获取到对应的配置项的值;

获取方式二:同样在Program.cs 中,配置

     var options = new ServiceOptions();builder.Configuration.GetSection("WcsSettings").Bind(wcsOptions);

获取方式一 同样的道理,都是直接通过 options.Code 获取到对应配置的值

最后一种使用情况:如果在 Program.cs 初始化时,同样需要临时使用 appsettings.json 节点的一些属性配置值,同时也需要把自定义的 ServiceOptions 类进行DI的注入,以便其他消费者类进行使用的话,可以这样去做,更加高效;

Program.cs 中,配置一

    builder.Services.AddOptions<ServiceOptions>().Bind(builder.Configuration.GetSection("Settings")).ValidateDataAnnotations(); // 自动验证注解 var options = new ServiceOptions();builder.Configuration.GetSection("Settings").Bind(options);

使用自动验证注解的方式,自定义类需要配置注解,Demo 示例如下:

如若缺少 ApiKey 将触发 [Required] 验证错误

public class AppSettings
{[Required(ErrorMessage = "API Key is required")]public string ApiKey { get; set; }[Range(1, 100, ErrorMessage = "MaxRetries must be between 1 and 100")]public int MaxRetries { get; set; }
}

自定义验证

    builder.Services.AddOptions<ServiceOptions>().Bind(builder.Configuration.GetSection("Settings")).ValidateDataAnnotations() // 内置验证支持.Validate(options => options.Timeout > 0, "Timeout 必须大于 0"); // 自定义验证 

启动时,立即验证支持

    builder.Services.AddOptions<ServiceOptions>().Bind(builder.Configuration.GetSection("Settings")).ValidateDataAnnotations().ValidateOnStart(); // 应用启动时立即验证配置 

配置二

     builder.Services.Configure<ServiceOptions>(builder.Configuration.GetSection("Settings"));var options = new ServiceOptions();builder.Configuration.GetSection("Settings").Bind(options);

这样子就实现了,即能在 Program.cs 中临时使用配置的属性和值,也能自动注入到DI容器中,给其他消费者类进行使用。

总结表格

特性services.Configure<T>()services.AddOptions<T>().Bind()
绑定配置✅ 直接绑定✅ 通过Bind方法绑定
DI注册✅ 注册IOptions<T>✅ 相同
链式配置❌ 不支持链式,只能单独调用✅ 支持链式,可接续配置验证、后置处理等
验证支持需要单独调用验证方法✅ 可链式调用验证(如.ValidateDataAnnotations()
启动验证需要额外步骤(如调用ValidateOnStart✅ 可链式调用.ValidateOnStart()
配置覆盖/调整只能通过多次调用Configure(顺序影响结果)✅ 可通过多个.Configure调用在绑定前后调整配置
推荐场景简单绑定,无需额外配置需要验证、复杂初始化或链式配置的场景

功能等价性与底层机制

  • 底层一致性
    两种方式最终都会调用相同的配置绑定逻辑。AddOptions<T>().Bind() 内部实际执行了 Configure<TOptions>(config) 的绑定过程,因此基础绑定功能完全等价
  • DI 注册效果相同
    无论使用哪种方式,都会将 IOptions<T>IOptionsSnapshot<T> 等接口注册到依赖注入容器,支持通过构造函数注入

结论

  • 功能上等价:两者在绑定配置部分没有区别,因为Bind内部调用了Configure
  • 灵活性AddOptions<T>提供了更流畅的API,便于添加验证和自定义配置,因此对于需要验证或复杂配置的场景,推荐使用AddOptions<T>().Bind()的方式。
  • 简洁性:如果只是简单绑定,使用Configure更简洁。
http://www.dtcms.com/a/512389.html

相关文章:

  • 25-DAPO: An Open-Source LLM Reinforcement LearningSystem at Scale
  • 6个网站建设网站设置保存登录密码怎么取消
  • 网站建设和维护的职责网站开发工程师有证书考试吗
  • 网站建设计算机人员招聘策划营销方案
  • 《i.MX6ULL LED 驱动实战:内核模块开发与 GPIO 控制》
  • Effective Java学习笔记:用静态工厂方法代替构造器(第一条)
  • TDengine 数学函数 POW 用户手册
  • AI大模型“战国策”:主流LLM平台简单介绍
  • Prometheus监控部署——pushgateway自动推送
  • 网站布局优化问问建设网站的人
  • 做网站宜宾深圳龙华网站建设公司
  • vue3 setup的平级函数(宏函数)
  • 企业门户网站开发代码游戏公司网站模板下载
  • 基于MATLAB的证件照片背景变换实例
  • 网站模板资源
  • 网站开发与托管协议诚信通旺铺网站建设
  • 做a图片网站公众号涨粉
  • 安卓实例——统一动画
  • 数字化转型:概念性名词浅谈(第七十三讲)
  • 【推荐系统】快手OneSearch 提升3.2%订单量
  • jsp做的网页是网站吗三亚网红
  • 网页浏览器图标电商网站如何优化
  • 几种常用关系型数据库详细介绍
  • R-CNN详解
  • 网站维护要求哈尔滨网站建设效果
  • 多线程:线程类的方法做什么
  • 网站快速备案安全开发公司抽奖送房
  • Java一、二维数组
  • 企业网站模板观叫湖南岚鸿团队discuz好还是wordpress
  • 定制网站开发系统wordpress 繁简转换插件