1. 程式人生 > >.NET Core採用的全新配置系統[4]: “Options模式”下各種型別的Options物件是如何繫結的?

.NET Core採用的全新配置系統[4]: “Options模式”下各種型別的Options物件是如何繫結的?

旨在生成Options物件的配置繫結實現在IConfiguration介面的擴充套件方法Bind上。配置繫結的目標型別可以是一個簡單的基元型別,也可以是一個自定義資料型別,還可以是一個陣列集合或者字典型別。通過前面的介紹我們知道ConfigurationProvider將原始的配置資料讀取出來後會將其轉成Key和Value均為字串的資料字典,那麼針對這些完全不同的目標型別,原始的配置資料如何通過資料字典的形式來體現呢? [ 本文已經同步到《ASP.NET Core框架揭祕》之中]

目錄
一、繫結簡單資料型別
二、繫結複雜資料型別
三、繫結集合物件
四、繫結字典

一、繫結簡單資料型別

我們先來說說針對簡單資料型別的配置繫結。這裡所謂的簡單資料型別和複雜資料型別只有一個界定標準,那就是是否支援源自字串型別的資料轉換。也就是說,簡單型別物件可以直接通過一個字串轉換而來,複雜型別物件則不能。如果目標型別是一個簡單型別,在進行配置繫結的時候只需要將配置項的值(體現為ConfigurationSection的Value屬性)轉換成對應的資料型別就可以了。

對於簡單型別的配置繫結,除了呼叫上述的擴充套件方法Bind來完成之外,我們其實還有更好的選擇,那就是呼叫IConfiguration介面的另一個擴充套件方法GetValue。GetValue方法總是將一個原子配置項的值(字串)轉換成目標型別,所以我們在呼叫該方法是除了指定目標型別之外,還需要通過引數key指定這個原子配置項相對於當前Configuration物件的路徑,也就是說引數key不僅僅可以指定為子配置項的Key(比如“Foo”),也可以設定為以下每個配置節相對於當前節點的路徑(比如“Foo:Bar:Baz”)。如果指定的配置節沒有值,或者配置節根本不存在,該方法會返回通過defaultValue引數指定的預設值。

   1: public static object GetValue(this IConfiguration configuration, Type type, string key, object defaultValue) ;

除了上述這個GetValue方法之外,IConfiguration介面還具有如下三個GetValue方法過載,它們最終都會呼叫上面這個方法來完成針對簡單型別的配置繫結。前面兩個方法以泛型引數的形式指定繫結的目標型別,如果沒有顯式指定預設值,意味著預設值為Null。

   1: public static T GetValue<T>(this
IConfiguration configuration, string key);
   2: public static T GetValue<T>(this IConfiguration configuration, string key, T defaultValue);

在下面這段程式中,我們我們演示了針對三種功能資料型別的配置繫結。前面兩種型別分別是Double和列舉,它們天生就是支援源自字串的簡單型別。第三種類型是我們自定義的表示二維座標點的Point,由於我們通過應用TypeConverterAttribute特性為它註冊了一個支援字串轉換的TypeConverter(PointTypeConverter),所示它也是一個簡單型別。

   1: Dictionary<string, string> source = new Dictionary<string, string>
   2: {
   3:     ["foo"] = "3.14159265",
   4:     ["bar"] = "Female",
   5:     ["baz"] = "(1.1, 2.2)"
   6: };
   7:  
   8: IConfiguration config = new ConfigurationBuilder()
   9:     .Add(new MemoryConfigurationSource { InitialData = source })
  10:     .Build();
  11:  
  12: Debug.Assert(config.GetValue<double>("foo") == 3.14158265);
  13: Debug.Assert(config.GetValue<Gender>("bar") == Gender.Female);
  14: Debug.Assert(config.GetValue<Point>("baz").X == 1.1);
  15: Debug.Assert(config.GetValue<Point>("baz").Y == 2.2);
  16:  
  17: public enum Gender
  18: {
  19:     Male,
  20:     Female
  21: }
  22:  
  23: [TypeConverter(typeof(PointTypeConverter))]
  24: public class Point
  25: {
  26:     public double X { get; set; }
  27:     public double Y { get; set; }
  28:        
  29:  
  30: }
  31: public class PointTypeConverter : TypeConverter
  32: {
  33:     public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
  34:     {
  35:         string[] split = value.ToString().Split(',');
  36:         double x = double.Parse(split[0].Trim().TrimStart('('));
  37:         double y = double.Parse(split[1].Trim().TrimEnd(')'));
  38:         return new Point { X = x, Y = y };
  39:     }
  40: }

二、繫結複雜資料型別

這裡所謂的複雜型別表示一個具有屬性資料成員的型別。如果通過一顆樹來表示一個複雜物件,那麼葉子節點承載所有的資料,並且葉子節點的資料型別均為簡單型別。如果通過資料字典來提供一個複雜物件所有的原始資料,那麼這個字典中只需要包含葉子節點對應的值即可。至於如何通過一個字典物件體現複雜物件的結構,我們只需要將葉子節點所在的路徑作為字典元素的Key就可以了。

   1: public class Profile
   2: {
   3:     public Gender         Gender { get; set; }
   4:     public int            Age { get; set; }
   5:     public ContactInfo    ContactInfo { get; set; }
   6: }
   7:  
   8: public class ContactInfo
   9: {
  10:     public string EmailAddress { get; set; }
  11:     public string PhoneNo { get; set; }
  12: }
  13:  
  14: public enum Gender
  15: {
  16:     Male,
  17:     Female
  18: }

如上面的程式碼片段所示,我們定義了一個表示個人基本資訊的Profile類,定義其中的三個屬性(Gender、Age和ContactInfo)分別表示性別、年齡和聯絡方式。表示聯絡資訊的ContactInfo物件具有兩個屬性(EmailAddress和PhoneNo)分別表示電子郵箱地址和電話號碼。一個完整的Profile物件可以通過如下圖所示的樹來體現。

8

如果需要通過配置的形式來表示一個完整的Profile物件,我們只需要將四個葉子節點(性別、年齡、電子郵箱地址和電話號碼)對應的資料定義在配置之中即可。對於承載配置資料的資料字典中,我們需要按照如下表所示的方式將這四個葉子節點的路徑作為字典元素的Key。

Key

Value

Gender

Male

Age

18

ContactInfo:Email

[email protected]

ContactInfo:PhoneNo

123456789

如上面的程式碼片段所示,我們建立了一個ConfigurationBuilder物件併為之添加了一個MemoryConfigurationProvider,後者按照如表2所示的結構提供了原始的配置資料。我們完全按照Options程式設計模式將這些原始的配置屬性繫結成一個Profile物件。

   1: Dictionary<string, string> source = new Dictionary<string, string>
   2: {
   3:     ["gender"]                       = "Male",
   4:     ["age"]                          = "18",
   5:     ["contactInfo:emailAddress"]     = "[email protected]",
   6:     ["contactInfo:phoneNo"]          = "123456789"
   7: };
   8:  
   9: IConfiguration config = new ConfigurationBuilder()
  10:     .Add(new MemoryConfigurationSource { InitialData = source })
  11:     .Build();
  12:  
  13: Profile profile = new ServiceCollection()
  14:     .AddOptions()
  15:     .Configure<Profile>(config)
  16:     .BuildServiceProvider()
  17:     .GetService<IOptions<Profile>>()
  18:     .Value;


三、繫結集合物件

這裡所說的集合型別指的是實現了ICollection <T>介面的所有型別。如果將一個集合通過一棵樹來表示,那麼可以將集合元素作為集合物件自身的子節點。 比如一個Options物件是一個元素型別為Profile的集合,它對應的配置樹具有如下圖所示的結構。

9

對於如上圖所示的這棵配置樹,我們採用零基索引(以零開頭的連續遞增整數)來表示每個Profile物件在集合中的位置。實際上針對集合物件的配置樹並無特別要求,它不要求作為索引的整數一定要從零開始(“1、2、3”這樣的順序也是可以得),也不要求它們一定具有連續性(“1、2、4”這樣的順序也沒有問題),甚至不要求索引一定是整數(可以使用任意字串作為索引)。下圖所示的這顆配置樹就採用字串(Foo、Bar和Baz)來作為集合元素的索引。

10 

既然我們能夠正確將集合物件通過一個合法的配置樹體現出來,那麼我們就可以將它轉換成配置字典。對於通過上圖表示的這個包含三個元素的Profile集合,我們可以採用如下面的表格所示的結構來定義對應的配置字典。

Key

Value

Foo:Gender

Male

Foo:Age

18

Foo:ContactInfo:Email

[email protected]

Foo:ContactInfo:PhoneNo

123

Bar:Gender

Male

Bar:Age

25

Bar:ContactInfo:Email

[email protected]

Bar:ContactInfo:PhoneNo

456

Baz:Gender

Female

Baz:Age

40

Baz:ContactInfo:Email

[email protected]

Baz:ContactInfo:PhoneNo

789

我們依然通過一個簡單的例項來演示針對集合的配置繫結。如下面的程式碼片段所示,我們建立了一個ConfigurationBuilder物件併為之添加了一個MemoryConfigurationProvider,後者按照如表3所示的結構提供了原始的配置資料。我們利用這個ConfigurationBuilder物件建立的Configuration物件並呼叫這個ConfigurationSection的Get方法將Key為“Profiles”的配置節繫結為一個List<Profile>物件。

在下面演示的程式碼片段中,我們按照上面表格所示的結構定義了一個Dictionary<string, string>物件,然後以此用建立了一個MemoryConfigurationSource,並將其註冊到建立的ConfigurationBuilder物件。我們利用後者生成的配置採用Options模式得到配置繫結生成的Collection<Profile>物件。

   1: Dictionary<string, string> source = new Dictionary<string, string>
   2: {
   3:     ["foo:gender"]                       = "Male",
   4:     ["foo:age"]                          = "18",
   5:     ["foo:contactInfo:emailAddress"]     = "[email protected]",
   6:     ["foo:contactInfo:phoneNo"]          = "123",
   7:  
   8:     ["bar:gender"]                       = "Male",
   9:     ["bar:age"]                          = "25",
  10:     ["bar:contactInfo:emailAddress"]     = "[email protected]",
  11:     ["bar:contactInfo:phoneNo"]          = "456",
  12:  
  13:     ["baz:gender"]                       = "Female",
  14:     ["baz:age"]                          = "36",
  15:     ["baz:contactInfo:emailAddress"]     = "[email protected]",
  16:     ["baz:contactInfo:phoneNo"]          = "789"
  17: };
            
           

相關推薦

.NET Core採用全新配置系統[4]: “Options模式各種型別的Options物件是如何的?

旨在生成Options物件的配置繫結實現在IConfiguration介面的擴充套件方法Bind上。配置繫結的目標型別可以是一個簡單的基元型別,也可以是一個自定義資料型別,還可以是一個陣列、集合或者字典型別。通過前面的介紹我們知道ConfigurationProvider將原始的配置資料讀取出來後會將其轉成K

AngularJS中ng-options實現拉列表的資料

下拉列表的簡單使用 ng-option指令使用很簡單,只需要繫結兩個屬性: 一個是ng-model用於獲取選定的值; 另一個是ng-options用於確定下拉列表的元素陣列。 <select ng-model="engineer.currentActivit

.NET Core採用全新配置系統[3]: “Options模式配置是如何結為Options物件

配置的原子結構就是單純的鍵值對,並且鍵和值都是字串,但是在真正的專案開發中我們一般不會單純地以鍵值對的形式來使用配置。值得推薦的做法就是採用《.NET Core採用的全新配置系統[1]: 讀取配置資料》最後演示的方式將相關的配置定義成一個Options型別,並採用與型別定義想匹配的結構來定義原始的配置,這樣就

.NET Core採用全新配置系統[7]: 將配置儲存在資料庫中

我們在《聊聊預設支援的各種配置源》和《深入瞭解三種針對檔案(JSON、XML與INI)的配置源》對配置模型中預設提供的各種ConfigurationSource進行了深入詳盡的介紹,如果它們依然不能滿足專案中的配置需求,我們可以還可以通過自定義ConfigurationProvider來支援我們希望的配置來源

.NET Core採用全新配置系統[2]: 配置模型設計詳解

在《.NET Core採用的全新配置系統[1]: 讀取配置資料》中,我們通過例項的方式演示了幾種典型的配置讀取方式,其主要目的在於使讀者朋友們從程式設計的角度對.NET Core的這個全新的配置系統具有一個大體上的認識,接下來我們從設計的維度來重寫認識它。通過上面演示的例項我們知道,配置的程式設計模型涉及到三

.NET Core採用全新配置系統[8]: 如何實現配置與原始檔的同步

配置的同步涉及到兩個方面:第一,對原始的配置檔案實施監控並在其發生變化之後從新載入配置;第二,配置重新載入之後及時通知應用程式進而使後者能夠使用最新的配置。接下來我們利用一個簡單的.NET Core控制檯應用來演示針對檔案的配置會涉及到資料同步的問題,我們希望應用能夠對原始配置檔案實施監控,並在檔案內容發生改

.NET Core採用全新配置系統[5]: 聊聊預設支援的各種配置源[記憶體變數,環境變數和命令列引數]

較之傳統通過App.config和Web.config這兩個XML檔案承載的配置系統,.NET Core採用的這個全新的配置模型的最大一個優勢就是針對多種不同配置源的支援。我們可以將記憶體變數、命令列引數、環境變數和物理檔案作為原始配置資料的來源,如果採用物理檔案作為配置源,我們可以選擇不同的格式(比如XML

.NET Core採用全新配置系統[6]: 深入瞭解三種針對檔案(JSON、XML與INI)的配置

物理檔案是我們最常用到的原始配置的載體,最佳的配置檔案格式主要由三種,它們分別是JSON、XML和INI,對應的配置源型別分別是JsonConfigurationSource、XmlConfigurationSource和IniConfigurationSource。 [ 本文已經同步到《ASP.NET Co

.NET Core採用全新配置系統[9]: 為什麼針對XML的支援不夠好?如何改進?

物理檔案是我們最常用到的原始配置的載體,最佳的配置檔案格式主要由三種,它們分別是JSON、XML和INI,對應的配置源型別分別是JsonConfigurationSource、XmlConfigurationSource和IniConfigurationSource。但是對於.NET Core的配置系統來說,

.NET Core採用全新配置系統[1]: 讀取配置資料

提到“配置”二字,我想絕大部分.NET開發人員腦海中會立馬浮現出兩個特殊檔案的身影,那就是我們再熟悉不過的app.config和web.config,多年以來我們已經習慣了將結構化的配置定義在這兩個檔案之中。到了.NET Core的時代,很多我們習以為常的東西都發生了改變,其中也包括定義配置的方式。總的來說,

.NET Core採用全新配置系統[10]: 配置的同步機制是如何實現的?

配置的同步涉及到兩個方面:第一,對原始的配置檔案實施監控並在其發生變化之後從新載入配置;第二,配置重新載入之後及時通知應用程式進而使後者能夠使用最新的配置。要了解配置同步機制的實現原理,先得從認識一個名為ConfigurationReloadToken的型別開始。 [ 本文已經同步到《ASP.NET Core

.Net Core和jexus配置HTTPS服務

spa log文件 https 個人 line fig rap 方式 phy 花了幾天時間,看了好多篇博客,終於搞定了網站的HTTPS服務,借此寫篇博客,來讓有需要的朋友少走彎路。 一、環境介紹   1、Linux下在Docker容器中部署好了一個網站,該網站需要通過外部提

.net core使用jexus配置https

操作系統 default 安全組 服務 博客 鏈接 添加 開發 最重要的 今天搞了一下怎麽從http換成https,寫一篇博客記錄該過程。關於jexus的安裝和使用請看我之前的一篇博客《Jexus部署Asp.Net Core項目》,唯一的不同是,將jexus升級成了

ASP.NET CORE 2.0 配置管理

ner TP 2.0 lin .com info spa namespace aaa 配置管理簡單例子(添加內存配置) using Microsoft.Extensions.Configuration; using System; using System.Col

Asp.net Core MVC 項目系統搭建與應用

開始 min 項目 pin mysql 高級 work ddd nbsp 第一部分 編程基礎 Asp.net Core 簡介 Asp.net Core 開始 Asp.net Core MVC 簡介 第二部分 基礎框架 Asp

ASP.NET Core多環境配置文件問題

指定 它的 png ati shel 前言 命令 服務器 ctrl+c 前言 在我們開發的過程中,往往會有這幾個環境,Dev、QA、Pre和Pro。 當然不同的環境可能大家的叫法會有點不一樣。 最常遇到的問題,或許就是不同環境的配置文件問題! 一個環境一個配置文件是很常見

ASP.NET Core 中的配置

ted .com 托管 lee obj 根據 webapi ocs 根目錄 前言 配置在我們開發過程中必不可少,ASP.NET中的配置在 Web.config 中。也可配置在如:JSON、XML、數據庫等(但ASP.NET並沒提供相應的模塊和方法)。 在ASP.NET

.net core 部署在Linux系統上執行的環境搭建總結

原文: .net core 部署在Linux系統上執行的環境搭建總結   安裝Linux用的是騰訊雲的centos7.5,需要安裝有環境有mysql5.7  .netcore2.1 nginx1.14 1.首先是mysql的安裝 我用的連結工具是putty,首先root登入系統

asp.net Core 跨域配置

1.新增中介軟體 在ConfigureServices中新增 //跨域中介軟體服務 services.AddCors();   在 Configure中新增   //跨域配置 app.UseCors(builder =&g

.NET Core SDK在Windows系統安裝後出現Failed to load the hostfxr.dll等問題的解決方法

這次無論如何也要記錄下,原因是今天在一臺Windows2008R2的電腦上安裝.NET Core SDK後再命令列執行dotnet --info 居然爆出了“Failed to load the hostfxr.dll”的問題,之前也遇到過,但是解決了,卻沒有做記錄,害的這裡又google了一把!所以寫篇文章