.NET 5 修改配置不重啟自動生效

.NET 5 修改配置不重啟自動生效

.NET Core,.NET5預設配置都是只載入一次,修改配置時都需要重啟才能生效,如何能修改即時生效呢?

最後更新 2021/9/18 上午11:35
包子wxl
預計閱讀 4 分鐘
分類
ASP.NET Core
標籤
.NET C# ASP.NET Core 設定檔

一、設定組態檔即時生效

1.1 設定

在 Program.cs 的 CreateHostBuilder() 處增加載入組態檔時,reloadOnChange:true。

這樣組態檔修改時,程式就會監聽到檔案發生變化,自動重新載入。

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((context, config) =>
            {
                config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();

            });

1.2 驗證

appsettings.json 檔案內容如下

{
  "TestSetting": "123",
  "AppOptions": {
    "UserName": "zhangsan"
  }
}

程式碼:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly IConfiguration _configuration;
    public HomeController(ILogger<HomeController> logger, IConfiguration configuration)
    {
        _logger = logger;
        _configuration = configuration;
    }

    public IActionResult Index()
    {
        string Name = _configuration["TestSetting"];
        string Name2 = _configuration["AppOptions:UserName"];
        ViewBag.Name = Name;
        ViewBag.Name2 = Name2;
        return View();
    }
}

介面顯示:

把組態檔修改為:

{
  "TestSetting": "abc",
  "AppOptions": {
    "UserName": "zhangsan123"
  }
}

重新整理頁面,已經發生變化:

1.3 IOptions 方式即時生效

新建 AppOptions.cs 類別

/// <summary>
/// 組態檔
/// </summary>
public class AppOptions
{
    public string UserName { get; set; }
}

在 Startup.cs 處把設定加到 Options

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.Configure<AppOptions>(Configuration.GetSection("AppOptions"));
}

使用:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly IConfiguration _configuration;
    private IOptionsMonitor<AppOptions> _options;

    public HomeController(ILogger<HomeController> logger, IConfiguration configuration, IOptionsMonitor<AppOptions> appOptions)
    {
        _logger = logger;
        _configuration = configuration;
        _options = appOptions;
    }

    public IActionResult Index()
    {
        string Name = _configuration["TestSetting"];
        string Name2 = _options.CurrentValue.UserName;
        ViewBag.Name = Name;
        ViewBag.Name2 = Name2;
        return View();
    }
}

IOptions 有三種方式

1. IOptions<T>          //站台啟動後,取得的值永遠不變
2. IOptionsMonitor<T>   //站台啟動後,如果組態檔有變化會發佈事件 (載入設定時,reloadOnChange:true 必須為 true)
3. IOptionsSnapshot<T>  //站台啟動後,每次取得的值都是組態檔裡的最新值 (載入設定時,reloadOnChange:true 必須為 true)

注意:

IOptionsMonitor<T> 和 IOptionsSnapshot<T> 的最大差別是前者可以被其他的 Singleton Services 使用而後者不可以,因為前者被註冊為 Singleton 而後者是被註冊為 Scoped,也就是說檔案被修改了前者會立即 Reload,而後者是在每個請求才被 Reload。

例:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private UserService _userService;

    public HomeController(ILogger<HomeController> logger, UserService userService)
    {

        _userService = userService;
    }

    public IActionResult Index()
    {
        string Name2 = _userService.GetName();
        ViewBag.Name2 = Name2;
        return View();
    }
}
public class UserService
{
    private IOptionsMonitor<AppOptions> _options;

    public UserService(IOptionsMonitor<AppOptions> appOptions)
    {
        _options = appOptions;
    }

    public string GetName()
    {
        var Name = _options.CurrentValue.UserName;
        return Name;
    }
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.Configure<AppOptions>(Configuration.GetSection("AppOptions"));
    services.AddSingleton<UserService>();
}

上面的 UserService 是單例注入的,透過 IOptionsMonitor<T> 的方式可以實現設定即時重新整理,而 IOptionsSnapshot<T> 啟動就會報錯。

1.4 多個組態檔載入即時生效

增加多一個 db 組態檔

修改 Program.cs 處 CreateHostBuilder(),也是載入時加上 reloadOnChange:true 就可以了。

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((context, config) =>
            {
                config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
                config.AddJsonFile("Configs/dbsetting.json", optional: true, reloadOnChange: true);
            })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();

                });

使用也一樣:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly IConfiguration _configuration;
    private AppOptions _options;
    public HomeController(ILogger<HomeController> logger, IConfiguration configuration, IOptionsMonitor<AppOptions> appOptions)
    {
        _logger = logger;
        _configuration = configuration;
        _options = appOptions.CurrentValue;
    }

    public IActionResult Index()
    {
        string Name = _configuration["TestSetting"];
        string Name2 = _configuration["db:connection1"];
        ViewBag.Name = Name;
        ViewBag.Name2 = Name2;
        return View();
    }
}
繼續探索

延伸閱讀

更多文章