您的位置:首页 > 其它

.NET Core基础篇之:配置文件读取

2021-11-23 18:28 78 查看

配置文件是每个项目最基础的部分,也是不可或缺的部分,比如:数据库连接、中间件属性等常见的配置。

今天这篇文章主要内容就是,在.Net Core项目中怎样去读取配置文件并使用。

###提前准备

appsettings.json
文件

{
"User": {
"userName": "赵一",
"userAge": 18
}
}

对应实体模型

public class UserOption
{
public string userName { get; set; }
public int userAge { get; set; }
}

###常规读取

#####1、注册 在 startup 类中注册,主要用到的是 Configure 方法:

services.Configure<UserOption>(Configuration.GetSection("User"));

#####2、控制器中注入并读取

public class HomeController : ControllerBase
{
private readonly UserOption user;

public HomeController(IOptions<UserOption> userOptions)
{
user = userOptions.Value;
}

[HttpGet]
public string Get()
{
return $"姓名:{user.userName},年龄:{user.userAge} ";
}
}

输出结果:

姓名:赵一,年龄:18

###嵌套读取 我们对

appsettings.json
文件做一点小小的改动,增加一个子节点
child

{
"User": {
"userName": "赵一",
"userAge": 18,
"child": {
"userName": "赵一的崽",
"userAge": 2
}
}
}

再对注册的代码做一点小小的修改:

services.Configure<UserOption>(Configuration.GetSection("User:child"));

输出结果:

姓名:赵一的崽,年龄:2

###分实例读取 这个时候需求又有变化了,需要同时读取

User
child
节点的数据,我们试试下面的方法看可行不可行:

// 注册
services.Configure<UserOption>(Configuration.GetSection("User"));services.Configure<UserOption>(Configuration.GetSection("User:child"));// 控制器
public class HomeController : ControllerBase
{
private readonly UserOption user;
private readonly UserOption child;

public HomeController(IOptions<UserOption> userOptions, IOptions<UserOption> childOptions)
{
user = userOptions.Value;
child = childOptions.Value;
}

[HttpGet]
public string Get()
{
return $"姓名:{user.userName},年龄:{user.userAge} \r\n姓名:{child.userName},年龄:{child.userAge}";
}
}

输出结果很显然满足不了我们的需求:

姓名:赵一的崽,年龄:2
姓名:赵一的崽,年龄:2

有的小伙伴肯定会说,在实体模型内在加一个子节点字段。这样肯定是没问题的,但是与常规读取方式就没什么两样了。

这里我要说的是分实例读取,引入

Configure
的另一个重载方法,与之前不同的是多了一个参数
name

public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, IConfiguration config) where TOptions : class;

下面我们重新注册:

services.Configure<UserOption>("father", Configuration.GetSection("User"));
services.Configure<UserOption>("son", Configuration.GetSection("User:child"));

在控制器构造函数中注入,也引入了一个新的接口对象:

IOptionsMonitor

public class HomeController : ControllerBase
{
private readonly UserOption user;
private readonly UserOption child;

public HomeController(IOptionsMonitor<UserOption> userOptions, IOptionsMonitor<UserOption> childOptions)
{
user = userOptions.Get("father");
child = childOptions.Get("son");
}

[HttpGet]
public string Get()
{
return $"姓名:{user.userName},年龄:{user.userAge} \r\n姓名:{child.userName},年龄:{child.userAge}";
}

输出结果:

姓名:赵一,年龄:18
姓名:赵一的崽,年龄:2

其实还有一个接口对象能实现这样的效果:

IOptionsSnapshot
,那
IOptionsMonitor
IOptionsSnapshot
有什么不同呢?请接着往下看。

###IOptionsMonitor与IOptionsSnapshot的不同之处

我们先来看看微软官方的注释:

IOptionsMonitor

//
// 摘要:
//     Used for notifications when TOptions instances change.
//
// 类型参数:
//   TOptions:
//     The options type.
public interface IOptionsMonitor<out TOptions>
{
//
// 摘要:
//     Returns the current TOptions instance with the Microsoft.Extensions.Options.Options.DefaultName.
TOptions CurrentValue { get; }

//
// 摘要:
//     Returns a configured TOptions instance with the given name.
TOptions Get(string name);
//
// 摘要:
//     Registers a listener to be called whenever a named TOptions changes.
//
// 参数:
//   listener:
//     The action to be invoked when TOptions has changed.
//
// 返回结果:
//     An System.IDisposable which should be disposed to stop listening for changes.
IDisposable OnChange(Action<TOptions, string> listener);
}

IOptionsSnapshot

//
// 摘要:
//     Used to access the value of TOptions for the lifetime of a request.
//
// 类型参数:
//   TOptions:
//     Options type.
public interface IOptionsSnapshot<out TOptions> : IOptions<TOptions> where TOptions : class, new()
{
//
// 摘要:
//     Returns a configured TOptions instance with the given name.
TOptions Get(string name);
}

从字面上理解,

IOptionsMonitor
建议在配置信息更改后需要通知的场景下使用,所以多了个
OnChange
的方法;而
IOptionsSnapshot
翻译过来的意思是:用于在请求的生命周期内访问配置,有点难以理解哈,我们接下来用代码来验证一下。

###IOptionsMonitor 与 IOptionsSnapshot的生命周期 我们对实体模型再做一点小小的修改,增加一个 guid 字段,并给上默认值:

public class UserOption
{
public string userName { get; set; }
public int userAge { get; set; }

public Guid guid { get; set; } = Guid.NewGuid();
}

我们再次运行程序:

father — 姓名:赵一,年龄:19,编号:e0d71f47-e8f1-4a6d-875e-2074c985f4a0
son — 姓名:赵一的崽,年龄:3,编号:d865151b-f9bf-4eff-bb4e-8ab6dc61160c

然后不停的刷新页面会发现,

father
的编号没有发生任何编号,而
son
的编号每次刷新都会改变。这是不是比较像我们注册时所用到的三种模式:

services.AddScoped();
services.AddTransient();
services.AddSingleton()

其中

father
类似
AddSingleton
son
则类似
AddScoped
AddTransient

其实只要看一看源码就知道了:

###IOptionsMonitor的OnChange调用方式

userOptions.OnChange((user,name)=> { Console.WriteLine(user.userName +"-"+ name); });

###无文件配置 无文件配置就是不需要以静态文件的方式进行配置。相关信息在配置一次后就不用再做修改,我们可以采用无文件配置的方式,比如我们熟悉的

AddCors
跨域配置

services.AddCors(op => {
op.AddPolicy(CorsName, set => {
set.SetIsOriginAllowed(origin => true).AllowAnyHeader().AllowAnyMethod().AllowCredentials();
});
});

我们对之前的注册方法进行一下改动:

services.Configure<UserOption>(c =>
{
c.userName = "钱二";
c.userAge = 60;
});

控制器注入采用常规的注入方式,最终输出结果:

姓名:钱二,年龄:60

以上就是本篇文章的全部内容了,因为时间有限,所以讲到的内容比较少,以后时间充裕之后再做相关补充。

分享一个源码查看网站:https://source.dot.net/

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: