ASP.NET Core中選項的應用和總結

在前面的文章中,我們介紹過將appsetting等配置文件映射到實體的的方式
https://www.cnblogs.com/fei686868/p/16779249.html

這裏呢,我們介紹關於選項的另一種用法,就是通過IOptions等選項來使用。

他們的區別呢,以前那種是隻實現映射,如果要注入,需要自己寫注入代碼;但使用IOptions等方式呢,是自動注入了,我們無需再寫注入代碼,

顯得更簡潔,同時呢,擴展性更強。

本文示例環境:netcore3.1

爲了演示代碼,我們在appsetting.json中新增一個配置和實體

  "Position": {
    "Title": "這個是標題",
    "Name": "這個是名稱"
  }
    public class PositionOptions
    {
        public const string Position = "Position"; //定義節點名稱,與配置對應。這邊定義只是爲了方便管理,不用到處寫字符串

        public string Title { get; set; }
        public string Name { get; set; }
    }

我們先看個簡單的寫法:

 services.Configure<實體名稱>(Configuration.GetSection("配置文件中的節點名稱"));

這裏我們採用的是services自帶的Configure<>方法進行處理。

下面上實際代碼:

Startup.cs中配置

      public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<PositionOptions>(Configuration.GetSection(PositionOptions.Position)); //映射和注入
           
        }

應用:

    public class PositionController : Controller
    {
        private readonly PositionOptions _positionOptions;
        public PositionController(IOptions<PositionOptions> options) //通過IOption實現注入
        {
            _positionOptions = options.Value;  //獲取對應的Value即可
        }
        public IActionResult Index()
        {
            string str = _positionOptions.Name; //這邊就能獲取到配置的Name了

            return View();
        }
    }

 

上面我們採用IOptions對象來處理,該方式呢,有個注意點:
不會讀取在應用啓動後對 JSON 配置文件所做的更改

就是啓動時讀取而已,如果配置文件改了,不會熱重載。但是在現實中,我們該配置,那還真會有。咋整?

選項有3種接口模式:

1、IOptions<TOptions>
  不支持熱重載

  不支持命名選項(下面會講什麼是命名選項)

  註冊爲單一實例且可以注入到任何服務生存期

2、IOptionsSnapshot<TOptions>

   支持熱重載,就是配置文件修改後,會更新。

   註冊爲Scope類型,因此無法注入到單一實例服務

   支持命名選項

3、IOptionsMonitor<TOptions>

    用於檢索選項並管理 TOptions 實例的選項通知

    註冊爲單一實例且可以注入到任何服務生存期。

    支持更改通知、命名選項、熱重載

 

不管用什麼方式,不影響Startup.cs中服務注入的Configure 方法的寫法。

對於日常項目應用來說,主要就是熱重載的區別。不同方式,性能影響也不太一樣。雖然有時候可以忽略性能差異。

有些配置是啓動後,就不需要再修改的,可以採用IOptions。否則,請使用後面兩種。

但相對來說,第3種更適合一點。

我們看看寫法

IOptionsSnapshot 寫法

    public class PositionController : Controller
    {
        private readonly PositionOptions _positionOptions;
        public PositionController(IOptionsSnapshot<PositionOptions> options) //通過IOption實現注入
        {
            _positionOptions = options.Value;  //獲取對應的Value即可
        }
        public IActionResult Index()
        {
            string str = _positionOptions.Name; //這邊就能獲取到配置的Name了

            return View();
        }
    }

IOptionsMonitor 寫法

    public class PositionController : Controller
    {
        private readonly PositionOptions _positionOptions;
        public PositionController(IOptionsMonitor<PositionOptions> options) //通過IOption實現注入
        {
            _positionOptions = options.CurrentValue;  //獲取對應的Value即可
        }
        public IActionResult Index()
        {
            string str = _positionOptions.Name; //這邊就能獲取到配置的Name了

            return View();
        }
    }

三者,寫法基本相同。

那我們先做個小總結
1、IOptions ,註冊爲單例,不支持熱重載。
2、IOptionsSnapshot,註冊爲Scope範圍,支持熱重載

3、IOptionsMonitor,註冊爲單例,支持熱重載。

下面我們再介紹下命名選項的情況,僅 IOptionsSnapshot和IOptionsMonitor 二者支持

我們換個例子,改下配置

{ 
"班級情況": {
    "1班": {
      "StudentCount": 50,
      "AvgScore": 80
    },
    "2班": {
      "StudentCount":60,
      "AvgScore": 90
    }
  }
}

加入配置是這樣的,那我們需要分別獲取1班和2班的學生數和平均分,怎麼獲取?

我們分析這種情況,出現了同層級,key名稱不一樣(1班,2班,這就是命名選項,同層級,不同key),而每個key對象的子內容是裏面是格式是一樣的。

我們就這麼寫,定義實體

    public class ClassData
    {
 public const string NodeName = "班級情況";
public const string ClasName1 = "1班"; public const string ClassName2 = "2班"; public int StudentCount { get; set; } public int AvgScore { get; set; } }

實體中,我們定義了兩個變量與節點一一對應

注入的時候是有變化的

   services.Configure<ClassData>( ClassData.ClassName1,Configuration.GetSection("班級情況:1班"));
            services.Configure<ClassData>(ClassData.ClassName2, Configuration.GetSection("班級情況:2班"));

看到了沒,得寫2個,分別寫。實體類型都一樣,但是 Configure方法的name參數不一樣。

應用端:

 private readonly ClassData _classData1;//1班
        private readonly ClassData _classData2;//2班
        public PositionController(IOptionsSnapshot<ClassData> options) //通過IOption實現注入
        {
            _classData1 = options.Get(ClassData.ClassName1); //分別獲取定義的name對應的數據
            _classData2 = options.Get(ClassData.ClassName2);
        }

再獲取數據時,需要用這種方式來獲取。

看起來是一小點的知識,其實在很多組件封裝上很實用。比如Abp就很多Configure方法,自己用多了,就更能理解了

以上,就是關於選項的一些小應用和總結。

更多分享,請大家關注我的個人公衆號:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章