只有累積,沒有奇蹟

2021年11月3日 星期三

[NETCore] ASP.NET Core 使用強型別取代 IOption 注入配置

前言
之前的 如何取得 appsettings.json 組態設定 文章中有介紹在 ASP.NET Core 中透過 IOptions 方法取得設定檔的方法,在需要用到的地方注入 IOptions 取得設定類別的資訊,相信使用上並不困難在 MSDN 官方推薦作法也是如此,但如果開發一陣子之後可以發現到處都是 IOptios 類別,這篇文章介紹如何使用擴充 IServiceCollection 的方法來降低對 IOptios 的依賴,若有問題或是錯誤的地方歡迎各方高手大大一起討論或給予指導

IOption
之首先先來簡單回顧  IOptions<T>  的傳統用法,透過微軟 MSDN 中 IOptions 介紹得知要使用前需先引用 Microsoft.Extensions.Options,為了方便快速了解差異性,這裡建立一個 ASP.NET Core Web 應用程式範例來說明,在新增完應用程式後在 appsetting.json 加入自己定義的  mySettings  設定資訊提供 Name 以及 Title 屬性
  1. "MySettings": {
  2. "Name": "Marcus",
  3. "Title": "9527"
  4. }
接著要取得設定檔的內容,這邊建立與 Config 內容欄位相同的強型別的 class 物件
  1. public class MySettings
  2. {
  3. public string Name { get; set; }
  4. public string Title { get; set; }
  5. }
在 ConfigureServices 中加入下列代碼,用意是將 appsettinss.json 中的資訊加載到 MySettings 中
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  4. services.AddOptions();
  5. services.Configure<MySettings>(Configuration.GetSection("MySettings"));
  6. }
接著就可以在 Value Controll 使用 IOptions<T> 取得設定檔的資訊,代碼如下
  1. public class ValuesController : ControllerBase
  2. {
  3. public MySettings _mySettings { get; set; }
  4.  
  5. public ValuesController(IOptions<MySettings> settings)
  6. {
  7. _mySettings = settings.Value;
  8. }
  9.  
  10. // GET api/values
  11. [HttpGet]
  12. public ActionResult<IEnumerable<string>> Get()
  13. {
  14. return new string[] { _mySettings.Name, _mySettings.Title };
  15. }

不使用 IOptions 注入
以上快速地回顧 IOptions<T> 的用法,就可以簡單使用 IOption<T> 取得 appsettings.json 設定資訊的方法,但是這意味著你的代碼與 IOptions 有著強制依賴的關係,你有多少 Controller 就需要在各別的 Controller 中都 using 所需要的 Microsoft.Extensions.Options,除非 appsettings.json 中的設定很常異動需要進行重新載入( 這時可以使用  IOptionMonitor  而不是 IOptions ),否則大部分的使用情境中 config 設定都是較少異動的,參考此文章之後有了新的解法,我們可以新增一個類別並針對 IServiceCollection 加入擴充方法,代碼如下
  1. public static class ServiceCollectionExtensions
  2. {
  3. public static TConfig ConfigurePOCO<TConfig>(this IServiceCollection services, IConfiguration configuration) where TConfig : class, new()
  4. {
  5. if (services == null) throw new ArgumentNullException(nameof(services));
  6. if (configuration == null) throw new ArgumentNullException(nameof(configuration));
  7.  
  8. var config = new TConfig();
  9. configuration.Bind(config);
  10. services.AddSingleton(config);
  11. return config;
  12. }
  13. }
這裡我們在 startup.cs 時手動使用  Microsoft.Extensions.Configuration.Binder  來綁定設定檔,並指定服務容器生命週期 (LifeTime) 為 Singleton,在 ASP.NET Core DI 預設提供的 Lifetime 有下列三種
  • Transient : 每次請求時都會產生新的 Instance
  • Scoped : 每個 http Request 都會產生一份 Instance
  • Singleton : 整個 Application 只會有一份 Instance
可以依據所需要情境作調整,如果想了解差異可以參考之前的文章 : 傳送門 

新增完擴充方法之後,接著下一步就是在 ConfigureServices 改用新增的擴充方法 confugurePOCO
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  4. services.AddOptions();
  5. services.ConfigurePOCO<MySettings>(Configuration.GetSection("MySettings"));
  6. //services.Configure<MySettings>(Configuration.GetSection("MySettings"));
  7. }
接著在回到要使用的地方也就是範例的 ValueController, 將 IOptions 依賴移除改為強行別的 MySettings
  1. public MySettings _mySettings { get; set; }
  2.  
  3. public ValuesController(MySettings settings)
  4. {
  5. _mySettings = settings;
  6. }
在重新執行應用程式,可以發現應用程式執行正常無誤
如果你對於擴充方法很熟悉,也可以針對自己的需求來自訂所需的方法簽章,例如新增一個 TConfig 參數做為繫結設定檔代碼如下
  1. public static class ServiceCollectionExtensions
  2. {
  3. public static TConfig ConfigurePOCO<TConfig>(this IServiceCollection services, IConfiguration configuration, TConfig config) where TConfig : class
  4. {
  5. if (services == null) throw new ArgumentNullException(nameof(services));
  6. if (configuration == null) throw new ArgumentNullException(nameof(configuration));
  7. if (config == null) throw new ArgumentNullException(nameof(config));
  8. configuration.Bind(config);
  9. services.AddSingleton(config);
  10. return config;
  11. }
  12. }
使用方式先 new 之後作為參數傳入
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc();
  4. var mySettings = new MySettings("foo");
  5. services.ConfigurePOCO(Configuration.GetSection("MySettings"), mySettings);
  6. }
或者是新增 Func<TConfig> 參數透過委派方法新增 TConfig 的 instance
  1. public static class ServiceCollectionExtensions
  2. {
  3. public static TConfig ConfigurePOCO<TConfig>(this IServiceCollection services, IConfiguration configuration, Func<TConfig> pocoProvider) where TConfig : class
  4. {
  5. if (services == null) throw new ArgumentNullException(nameof(services));
  6. if (configuration == null) throw new ArgumentNullException(nameof(configuration));
  7. if (pocoProvider == null) throw new ArgumentNullException(nameof(pocoProvider));
  8.  
  9. var config = pocoProvider();
  10. configuration.Bind(config);
  11. services.AddSingleton(config);
  12. return config;
  13. }
  14. }
使用方式如下
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. //...
  4. services.ConfigurePOCO(Configuration.GetSection("MySettings"), () => new MySettings("foo"));
  5. //...
  6. }
如果想了解更多細節,可以參考 Strongly typed configuration in ASP.NET Core without IOptions<T> 取得更多資訊,希望透過以上的介紹,可以讓跟我有一樣困擾的開發者得到新的作法,Hope it helps :)

Related Posts:

  • [.NETCore] 在 IIS 執行 ASP.NET Core 應用程式前言 在 IIS 執行 ASP.NET Core 專案時與過去 .NET Framework 運作不同,.NET Core Application 預設以 Kestrel 為 HTTP Server 與 IIS 做溝通,流程可以參考下圖所示;因此要將開發好的 .NET Core 網站專案佈署至 IIS 設定方式是不同的,這篇介紹如何將 ASP.NET Core 應用程式佈署至 IIS 的步驟說明,若有問題歡迎提出一起討論或是給予指導 … Read More
  • [NETCore] ASP.NET Core 啟動異常 - HTTP Error 500.30 - ANCM In-Process Start Failure 問題  在開發專案時跳出異常訊息,錯誤訊息為  HTTP Error 500.30 - ANCM In-Process Start Failure ,這篇就針對此案例作簡單紀錄與分享,若是有不清楚或是錯誤的地方歡迎討論予糾正。 解決方法  廢話不多說,先看案發現場的錯誤畫面 執行異常的程式代碼,看起來很單純的代碼 public static void Main(s… Read More
  • [NETCore] 在 ASP.NET Core Web API 中使用 Serilog 前言 近期專案都在嘗試 Serilog,對於使用上有點小小心得,因此整理這篇文章分享 Serilog 在 ASP.NET Core API 上的使用與設定,也接續之前 Serilog 的系列介紹文 : 傳送門 的實際應用心得,希望可以幫到有需要的朋友,若有問題或是錯誤的地方歡迎提出來一起討論或是給予指導。 ASP.NET Core logging 首先先建立新的 ASP.NET Core Web Applicat… Read More
  • [NETCore] ASP.NET Core 3.0 Preview 體驗 前言 ASP.NET Core 3.0 preview 5 已經推出,在 3.0 最大的變化是對 windows desktop application 的支援, 以及支援 .NET Standard 2.1 和可以在 Visual Studio 2019 上使用 C# 8.0 功能,這篇文章紀錄安裝 ASP.NET Core 3.0 SDK 以及 升級 Visual Studio 2019 Update,若有問題或是錯誤的地方歡迎提出來一起討… Read More
  • [Docker] Docker for windows 初體驗前言 Docker 是一個 open source 專案,誕生於 2013 年初,Docker 屬於 Linux 容器的一種封裝,提供了簡單且易用的容器接口,在 2016 推出 Docker for windows 版本,相信大家或多或少都聽過甚至已經有在使用,自己也接觸過 docker 一小段時間,但都屬於玩票性質未好好研究,或許在新筆電重新安裝的時候是一個好契機可以靜下心來深入研究,以下簡單介紹 Docker 在 Windows 上的安裝流程… Read More

1 則留言:

Copyright © 2025 m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com