草庐IT

02-《AspNetCore》-Configuration

花间岛 2023-03-28 原文

Configuration

视频讲解

package说明

Microsoft.Extensions.Configuration.Abstractions:抽象包,一大堆的接口

Microsoft.Extensions.Configuration.Binder:提供一大堆的扩展,比如类型转换

Microsoft.Extensions.Configuration.Json:json实现

Microsoft.Extensions.Configuration.CommandLine:命令行实现

Microsoft.Extensions.Configuration.EnvironmentVariables:环境变量实现

Microsoft.Extensions.Primitives:ChangeToken

基本使用

//创建配置管理器
ConfigurationManager configuration = new ConfigurationManager();
configuration.SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("config.json")//添加json文件
    .AddEnvironmentVariables();//添加系统环境变量
//打印环境变量
Console.WriteLine(configuration.GetSection("path").Value);
//读取josn
var student = configuration.GetSection("student");
Console.WriteLine(student["name"]);
Console.WriteLine(configuration["student:name"]);
//类型转换:需要安装Microsoft.Extensions.Configuration.Binder支持
Console.WriteLine(configuration.GetSection("student:age").Get<int>());

自定义

IConfigurationProvider:表示我们的配置的数据源,可以是任意形式具体由自己实现,但是你必须处理成key-value的形式。

IConfigurationSource:用于配置和构建IConfigurationProvider的派生类型

//配置提供器选项:用于提供配置选项
public class IsonConfigurationSource : IConfigurationSource
{
    public string? Url { get; set; }
    public bool ReloadOnChange { get; set; }

    public IsonConfigurationSource()
    {

    }

    public IsonConfigurationSource(string url)
    {
        Url = url;
    }

    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        if (Url == null)
        {
            throw new ArgumentNullException(nameof(Url));
        }
        return new IsonConfigurationProvider(this);
    }
}
//配置提供器:配置源逻辑
public class IsonConfigurationProvider : IConfigurationProvider
{
    private ConcurrentDictionary<string, string> values = new ConcurrentDictionary<string, string>();
    private IsonConfigurationSource options;
    private CancellationTokenSource? tokenSource;
    public IsonConfigurationProvider(IsonConfigurationSource options)
    {
        this.options = options;
        //如果需要监听
        if (this.options.ReloadOnChange)
        {
            Watch();
        }
    }
    private void Watch()
    {
        //注册事件
        ChangeToken.OnChange(GetReloadToken, () =>
        {
            Load();

        });
        //模拟更改
        var t = new Thread(() =>
        {

            while (true)
            {
                var token = tokenSource;
                tokenSource = null;
                //每3s之后发生更改
                Thread.Sleep(3000);
                //触发事件,触发之前一定要将tokenSource设置成null
                token!.Cancel();
            }
        });
        t.Start();
    }
    public IEnumerable<string> GetChildKeys(IEnumerable<string> earlierKeys, string parentPath)
    {
        return values.Keys;
    }

    public IChangeToken GetReloadToken()
    {
        lock (this)
        {
            if (tokenSource == null)
            {
                tokenSource = new CancellationTokenSource();
            }
            return new CancellationChangeToken(tokenSource!.Token);
        }
    }

    public void Load()
    {
        //假设我们从第三方地址获取
        //var client = new HttpClient();
        //var response = client.GetAsync(source.Url).GetAwaiter().GetResult();
        //var json = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
        values.TryAdd("t1", "1111111");
        values.TryAdd("t2", "2222222");
        Console.WriteLine("ison文件已加载...");
    }

    public void Set(string key, string value)
    {
        values.TryAdd(key, value);
    }

    public bool TryGet(string key, out string value)
    {
        var flag = values.TryGetValue(key, out string? data);
        value = data ?? string.Empty;
        return flag;
    }
}


//扩展IConfigurationBuilder
public static class IsonConfigurationExtensions
{
    public static IConfigurationBuilder AddJsonUrl(this IConfigurationBuilder builder, string url)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }
        if (string.IsNullOrEmpty(url))
        {
            throw new ArgumentException(nameof(url));
        }

        return builder.Add(new IsonConfigurationSource(url));
    }

    public static IConfigurationBuilder AddJsonUrl(this IConfigurationBuilder builder, Action<IsonConfigurationSource> configure)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        var source = new IsonConfigurationSource();
        configure(source);//执行用户配置
        return builder.Add(source);
    }


ChangeToken

ChangeToken:将changeToken生产者和changeToken消费者进行绑定。

IChangeToken:传播已发生更改的通知(也可以自己实现)。可以注册回调在事件发生时执行。

CancellationChangeToken:IChangeToken的一种实现,通过取消令牌来进行通知。

CancellationTokenSource:通知CancellationToken,告知其应被取消,执行回调。

internal class Program
{
    static void Main(string[] args)
    {
        var provider = new FileConfigurationProvider();
        //绑定
        provider.Watch();
        new TaskCompletionSource().Task.Wait();
    }
}

/// <summary>
/// 文件配置程序超类
/// </summary>
public class FileConfigurationProvider
{
    private CancellationTokenSource? tokenSource;

    public void Load()
    {
        Console.WriteLine($"[{DateTime.Now}]文件已加载...");
    }

    public void Watch()
    {
        //将changeToken生产者和changeToken消费者进行绑定(订阅)
        ChangeToken.OnChange(GetReloadToken, Load);
        //触发Change事件,通知更新
        var t = new Thread(() =>
        {
            while (true)
            {
                Thread.Sleep(3000);
                var t = tokenSource;
                tokenSource = null;
                //注意,取消之前一定要将tokenSource设置成null,不然会引发堆栈异常
                //因为通知了取消,就会获取changeChange,但是你没有设置成null,OnChange认为又发生了取消通知
                //会一直循环
                t!.Cancel();//执行回调,发布取消事件。
            }
        });
        t.Start();
    }

    /// <summary>
    /// 更新令牌,通过该令牌可以注册回调,用于执行更新通知。
    /// </summary>
    /// <returns></returns>
    public IChangeToken GetReloadToken()
    {
        lock (this)
        {
            //如果被消费就创建一个新的
            if (tokenSource == null)
            {
                tokenSource = new CancellationTokenSource();
            }
            return new CancellationChangeToken(tokenSource.Token);
        }
    }

}

有关02-《AspNetCore》-Configuration的更多相关文章

  1. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  2. 牛客网专项练习30天Pytnon篇第02天 - 2

    1.在Python3中,下列关于数学运算结果正确的是:(B)a=10b=3print(a//b)print(a%b)print(a/b)A.3,3,3.3333...B.3,1,3.3333...C.3.3333...,3.3333...,3D.3.3333...,1,3.3333...解析:    在Python中,//表示地板除(向下取整),%表示取余,/表示除(Python2向下取整返回3)2.如下程序Python2会打印多少个数:(D)k=1000whilek>1:    print(k)k=k/2A.1000 B.10C.11D.9解析:    按照题意每次循环K/2,直到K值小于等

  3. ruby - 如何将 Puma::Configuration 传递给 Sinatra? - 2

    这是我的网络应用:classFront我是这样开始的(请不要建议使用Rack):Front.start!这是我的Puma配置对象,我不知道如何传递给它:require'puma/configuration'Puma::Configuration.new({log_requests:true,debug:true})说真的,怎么样? 最佳答案 配置与您运行的方式紧密相关puma服务器。运行的标准方式puma-pumaCLI命令。为了配置puma配置文件config/puma.rb或config/puma/.rb应该提供(参见examp

  4. ruby-on-rails - `method_missing':#<Rails::Application::Configuration:0x00> 的未定义方法 `action_mailer' - 2

    我正在构建一个Rails应用程序并且使用的是Rails4.0.1。我有一个错误,并注意到它在3个月前被称为rails上的一个错误,所以我决定:捆绑更新并获得rails4.0.3这样做之后,测试和服务器都不会启动,并且会抛出错误:gems/railties-4.0.3/lib/rails/railtie/configuration.rb:95:in`method_missing':undefinedmethod`action_mailer'for#(NoMethodError)目前我在config/environments/*中注释掉了action_mailer行,但最好能找到一个真正的

  5. ruby-on-rails - rails : Could not load database configuration. 没有这样的文件 - - 2

    我从GitHub存储库克隆了一个应用程序文件夹,在捆绑安装gems之后,我尝试使用rakedb:setup和rakedb:migrate命令,但都没有用,这是我的错误消息:**arun997@promanager:~/workspace(master)$rakedb:setuprequire'rails/all'...2.470sBundler.require...7.590srakeaborted!Cannotload`Rails.application.database_configuration`:Couldnotloaddatabaseconfiguration.Nosuchf

  6. Ruby:为什么 1.025.round(2) 四舍五入为 1.02? - 2

    据我了解.round()-ruby中的功能将小数向上舍入,最后一个有效数字是5?例如1.5.round(0)#=>2(OK)但为什么1.025.round(2)#=>1.02而不是我期望的1.03?irb(main):037:0>1.025.round(2)=>1.02我该怎么做才能解决这个问题? 最佳答案 这与最后一位数字为5无关,与将十进制值转换为double浮点值有关。http://en.wikipedia.org/wiki/Double_precision_floating-point_format基本上,十进制数必须以有限

  7. ruby-on-rails - 未初始化常量 > ActionCable::Server::Configuration::ApplicationCable - 2

    当我运行服务器时,它的抛出错误显示在下面的日志中。我在谷歌上搜索了很多,但没有找到背后的原因。有人请点亮它。gem文件source'https://rubygems.org'#BundleedgeRailsinstead:gem'rails',github:'rails/rails'gem'rails','>=5.0.0.beta1','0.10.0.rc1'group:development,:testdogem'byebug'endgem'puma'group:developmentdogem'spring'end日志:/home/pd/.rvm/gems/ruby-2.2.4/g

  8. ruby-on-rails - Capistrano::Configuration:Class 的未定义方法 `instance' - 2

    我正在尝试在Rails应用程序中首次启动并运行Capistrano。我有一台运行Ubuntu12.04、nginx、unicorn和rails的linux服务器,但是,我似乎遇到了一些问题。我还使用RVM使用Capistrano3.0.0、rails3.2.14、bundler1.4.0和ruby​​1.9.3p448。我只设置了一个生产阶段,此时我只关心Capistrano与我的服务器通信并从github推送我的代码(目前还没有迁移和捆绑等)。当我使用下面的设置尝试命令capproductiondeploy:check或capproductiondeploy:setup(这似乎已被弃

  9. Elasticsearch--02.Kibana8.1.0安装 - 2

    1.下载安装概述:Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana,可以通过各种图表进行高级数据分析及展示。下载地址:Kibana8.1.0|Elastic解压到指定目录:tar-xzvfkibana-8.1.0-linux-x86_64.tar.gz-C/opt/module/2.Kibana生成证书文件在es服务器中生成证书、直接回车cd/opt/module/elasticsearch-8.1.0/bin/elasticsearch-certutilcsr-namekibana-dns

  10. 【愚公系列】2023年02月 微信小程序-Flex布局详解 - 2

    文章目录一、Flex布局详解1.Flex布局的概念1.1传统布局1.2Flex布局1.3Flex布局声明2.Flex布局的容器属性2.1flex-direction属性2.2flex-wrap属性2.3flex-flow属性2.4justify-content属性2.5align-items属性2.6align-content属性3.Flex布局的项目属性3.1order属性3.2flex-grow属性3.3flex-shrink属性3.4flex-basis属性3.5flex属性3.6align-self属性总结一、Flex布局详解1.Flex布局的概念1.1传统布局盒子模型:我们知道当并列

随机推荐