选项是配置一个升级版,一般情况下是把一个范围内的配置包装成类型,以供使用,比如下面的RedisSetting,是Redis的配置参数:

{"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": "*", "RedisSetting": {"Host": "127.0.0.1","Port": 6379,"Password": "123","ConnectionTimeOut": "10ms"}
}

可以采用下面的形式把配置类型 实体注入到容器(因为没有说注入这个知识点,这里可以理解为初始化)中。

var builder = WebApplication.CreateBuilder();
builder.Services.Configure<RedisSetting>(builder.Configuration.GetSection("RedisSetting"));
var app = builder.Build();

选项分为三种:普通选项目IOptions,热更新选项IOptionsSnapshot,监控选项IOptionsMonitor,下面分别说明。

IOptions选项

app.MapGet("/appinfo", (IOptions<RedisSetting> options) =>
{return options.Value;
});

Demo结果

热加载选项:IOptionsSnapshot

app.MapGet("/snapshot", (IOptionsSnapshot<RedisSetting> options) =>
{return options.Value;
});

结果

更新配置ConnectionTimeOut为15ms,在不重启服务的情况下,再次请求,结果会变成15ms

监控选项:IOptionsMonitor

app.MapGet("/monitorstart", (IOptionsMonitor<RedisSetting> options) =>
{options.OnChange(redisSetting =>{app.Logger.LogInformation(options.CurrentValue.ToString());     });return "Ok";
});

调用监控

当把ConnectionTimeOut更新成20ms时,OnChange会被触发,日志会打印出来

利用监控特性可以与报警联合起来,当监控到配置有变化时,通知服务相关人知晓,是人为设置,还是被篡改,以便采取措施。

选项命名:

当相同的配置有两组时,选项命名就非常有用了,比如一主一备

"RedisSettings": {"Main": {"Host": "127.0.0.1","Port": 6379,"Password": "123","ConnectionTimeOut": "10ms"},"Prepare": {"Host": "127.0.0.1","Port": 6380,"Password": "456","ConnectionTimeOut": "12ms"}}

实体类可以用静态常量区分开来

public record RedisSetting
{public const string Main = "Main";public const string Prepare = "Prepare";public string? Host { get; set; }public int Port { get; set; }public string? Password { get; set; }public string? ConnectionTimeOut { get; set; }
}

分别注入配置即可

builder.Services.Configure<RedisSetting>(RedisSetting.Main,builder.Configuration.GetSection("RedisSettings:Main"));
builder.Services.Configure<RedisSetting>(RedisSetting.Prepare,builder.Configuration.GetSection("RedisSettings:Prepare"));

不过只有IOptionsSnapshot和IOptionsMonitor能通过Get方法来获取命名的配置,IOptions没有实现Get方法

app.MapGet("/snapshotredissetting", (IOptionsSnapshot<RedisSetting> options) =>
{return options.Get(RedisSetting.Main);
});
app.MapGet("/monitorstart", (IOptionsMonitor<RedisSetting> options) =>
{options.OnChange(redisSetting =>{app.Logger.LogInformation(options.Get(RedisSetting.Main).ToString());app.Logger.LogInformation(options.Get(RedisSetting.Prepare).ToString());});return options.CurrentValue;
});

另外,为了提高配置数据的安全性,可以给配置选项增加验证,可以通过在配置实体类上增加DataAnnotations来验证,也可以自定义验证

public record RedisSetting
{public string? Host { get; set; }public int Port { get; set; }public string? Password { get; set; }[RegularExpression(@"^\d+ms$", ErrorMessage = "格式不正确,必须是ms")]public string? ConnectionTimeOut { get; set; }
}

上面的ConnectionTimeOut是DataAnnotations方式,下面是自定义验证模式。

builder.Services.AddOptions<RedisSetting>().Bind(builder.Configuration.GetSection("RedisSetting")).ValidateDataAnnotations().Validate(config =>{if (config.Port < 1000){return false;}return true;}, "端口不能少于1000");

如果验证更复杂,可以自定义类实现,如下:

public class RedisSettingValidation : IValidateOptions<RedisSetting>
{public RedisSetting _config { get; init; }public RedisSettingValidation(IConfiguration config){_config = config.GetSection("RedisSetting").Get<RedisSetting>();}public ValidateOptionsResult Validate(string name, RedisSetting options){string? vor=null;var rx = new Regex(@"^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$");if (options != null&&options.Host!=null){var match = rx.Match(options.Host);if (string.IsNullOrEmpty(match.Value)){vor = $"{options.Host} 格式不正确";}if (vor != null){return ValidateOptionsResult.Fail(vor);}}return ValidateOptionsResult.Success;}
}

添加验证类型

builder.Services.Configure<RedisSetting>(builder.Configuration.GetSection("RedisSetting"));
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IValidateOptions<RedisSetting>, RedisSettingValidation>());

.NET6之MiniAPI(五):选项相关推荐

  1. .NET6之MiniAPI(三十):结束篇(附链接)

    不知不觉来到了<.NET6之MiniAPI>的第三十篇,回顾之前的篇幅,主要涉及如下: HTTP请求,应答 Request 桂素伟,公众号:桂迹.NET6之MiniAPI(二):reque ...

  2. .NET6之MiniAPI(十九):NLog

    在本系例文章的第八篇中,我们聊过官方的日志实现,即<.NET6之MiniAPI(八):日志>.但官方的日志功能更多是提供了一个实现基础,对于要求一个灵活,强大,方便的日志体系,官方的还是有 ...

  3. vue项目实践教程3:中间大的五选项底部切换卡制作及相关问题解决

    在移动端项目中,有不少项目会有底部切换卡的功能需求,类似于app应用,点击底部不同的切换卡,显示不同的界面,表现不同的功能. 这里,笔者展示一个采用vux-uid 五选项切换卡,同时,中间的选项卡比较 ...

  4. .NET6之MiniAPI(十五):跨域CORS(下)

    前一篇的跨域请求的方式是松宽的方式,毕竟跨域有安全风险,应尽量少的允许访问必要资源,本篇分别从请求方法,请求头和请求凭据方面了解跨域设置. 请求方法: api项目,get,post是默认访问,这里只设 ...

  5. .NET6之MiniAPI(二十五):Dapper

    注:如果你使用Dapper一段时间了,这篇你可以跳过去了. 在第十二篇中,我们聊过官方的ORM--EntityFramework,它可以把SQL细节都隐藏,这对于一些标准化的关系数据库项目非常便捷.今 ...

  6. .NET6之MiniAPI(十八):OpenAPI swagger

    从本篇开始,介绍一些很不错的三方库,来丰富MiniAPI的使用. 在创建MiniAPI项目时,模板提供了一个是否启用OpenAPI的选项,足见这个三方库的优势和强大. OpenAPI为我们测试API提 ...

  7. .NET6之MiniAPI(二十七):Metrics

    应用的各种Metrics是保证应用健康稳定运行的基础,特别对于一些可用性有所要求的应用,本文介绍prometheus-net这个三方指示库. prometheus-net的工作原理是,在应用内部埋点, ...

  8. .NET6之MiniAPI(二十九):UnitTest

    MiniAPI的单元测试与asp.net web api的单元测试大体是相同的(毕竟都是asp.net core),只是在小细节上有一些差异,文章中会说到这点. 本文测试框架是XUnit,Mock框架 ...

  9. .NET6之MiniAPI(十四):跨域CORS(上)

    为了说明跨请求,创建了两个项目,一个mini api,端口是5001,另一个razor page项目,端口是5280.5280项目会在页面用ajax的方式来请求5001,形成跨域请求,由于是本地测试, ...

最新文章

  1. android控件触摸缩放,Android控件之ZoomControls缩放使用
  2. python简单还是c简单_Python与C的简单比较(Python3.0)
  3. Invoke()/BeginInvoke()区别
  4. pandas处理excel文件和csv文件
  5. 380免费云存储_三款功能强大的云盘软件,完全替代百度云与腾讯云
  6. 用计算机表白的数字,用数字表白
  7. 记录——《C Primer Plus (第五版)》第十章编程练习第四题
  8. Shell:export命令
  9. 【从C到C++学习笔记】bool类型/const限定符/#define//结构体对齐
  10. 电子表格计算机时间格式,在Excel表格中输入日期的五种方法与技巧
  11. linux环境下安装cwp的地震专业软件su
  12. IoT with Mongodb cloud
  13. 视频教程-系统集成项目管理工程师考试历年真题讲解-软考
  14. 从neo4j-broswer中剥离graph图表
  15. 使用K-Fold训练和预测XGBoost模型的方法
  16. 一生一世的承诺win7主题——rmzt.com
  17. people who change the files in the active changelist also change
  18. 阿尔法大蛋智能机器人功能_科大讯飞机器阿尔法蛋大蛋2.0怎么样?儿童智能机器人阿尔法蛋大蛋2.0和1.0区别对比!...
  19. 软件开源真正意义何在?
  20. 华为员工的命 只值一台交换机的钱 【 华为员工 胡新宇 过劳死 最新报道 】

热门文章

  1. 0330Cache Buffers chains与共享模式疑问
  2. MySQL大批量数据插入
  3. linux下无法umount移动设备
  4. redis存opc_Redis集群的三种模式
  5. 【原理图操作】原理图更新PCB时未改动元器件布局变动问题?
  6. MVC中提交表单的4种方式
  7. POJ 1986 Distance Queries(LCA)
  8. mysql通过data目录恢复数据库
  9. 改变listview中item选中时文字的颜色
  10. Teams App设备的地理位置能力