《ASP.NET Core 6框架揭秘》實例演示[25]:配置與承載環境的應用

與服務注冊一樣,針對配置的設置同樣可以采用三種不同的編程模式。第一種是利用WebApplicationBuilder的Host屬性返回的IHostBuilder對象,它可以幫助我們設置面向宿主和應用的配置。IWebHostBuilder接口上面同樣提供了一系列用來對配置進行設置的方法,我們可以將這些方法應用到WebApplicationBuilder的WebHost屬性返回的IWebHostBuilder對象上。不過還是那句話,既然推薦使用Mininal API,最好還是采用最新的編程方式。[本文節選《ASP.NET Core 6框架揭秘》第15章]

[S1513]基于環境變量的配置初始化(源代碼)
[S1514]以鍵值對形式讀取和修改配置(源代碼)
[S1515]注冊配置源(利用IWebHostBuilder)(源代碼)
[S1516]注冊配置源(Minimal API)(源代碼)
[S1517]默認的承載環境(源代碼)
[S1518]通過配置定制承載環境(源代碼)
[S1519]利用WebApplicationOptions定制承載環境(源代碼)

[S1513]基于環境變量的配置初始化

應用啟動的時候會將當前的環境變量作為配置源來創建承載最初配置數據的IConfiguration對象,但它只會選擇名稱以“ASPNETCORE_”為前綴的環境變量(通過靜態類型Host的CreateDefaultBuilder方法創建的HostBuilder默認選擇的是前綴為“DOTNET_”的環境變量)。在演示針對環境變量的初始化配置之前,需要先解決配置的消費問題,即如何獲取配置數據。如下面的代碼片段所示,我們設置兩個環境變量,它們的名稱分別為"ASPNETCORE_FOO"和"ASPNETCORE_BAR"。在調用WebApplication的CreateBuilder方法創建出WebApplicationBuilder對象之后,我們將它的Configuration屬性提取出來。由調試斷言可以看出這兩個環境變量被成功轉移到配置中了。代表承載應用的WebApplication構建出來后,其Configuration屬性返回的IConfiguration對象上同樣包含著相同的配置。

using?System.Diagnostics;Environment.SetEnvironmentVariable("ASPNETCORE_FOO",?"123");
Environment.SetEnvironmentVariable("ASPNETCORE_BAR",?"456");var?builder?=?WebApplication.CreateBuilder(args);
IConfiguration?configuration?=?builder.Configuration;
Debug.Assert(configuration["foo"]?==?"123");
Debug.Assert(configuration["bar"]?==?"456");var?app?=?builder.Build();
configuration?=?app.Configuration;
Debug.Assert(configuration["foo"]?==?"123");
Debug.Assert(configuration["bar"]?==?"456");

[S1514]以鍵值對形式讀取和修改配置

我們知道IConfiguration對象是以字典的結構來存儲配置數據的,我們可以利用該對象提供的索引以鍵值對的形式來讀取和修改配置。在ASP.NET Core應用中,我們可以通過調用定義在IWebHostBuilder接口的GetSetting方法和UseSetting方法達到相同的目的。

public?interface?IWebHostBuilder
{string?GetSetting(string?key);IWebHostBuilder?UseSetting(string?key,?string?value);...
}

如下面的代碼片段所示,我們可以通過利用WebApplicationBuilder的WebHost屬性將對應的IWebHostBuilder對象提取出來,通過調用其GetSetting方法將以環境變量設置的配置提取出來。通過調用其UseSetting方法提供的鍵值對會保存到應用的配置中。配置最終的狀態被固定下來后轉移到了構建的WebApplication對象上。

using?System.Diagnostics;var?builder?=?WebApplication.CreateBuilder(args);
builder.WebHost.UseSetting("foo",?"abc");
builder.WebHost.UseSetting("bar",?"xyz");Debug.Assert(builder.WebHost.GetSetting("foo")?==?"abc");
Debug.Assert(builder.WebHost.GetSetting("bar")?==?"xyz");IConfiguration?configuration?=?builder.Configuration;
Debug.Assert(configuration["foo"]?==?"abc");
Debug.Assert(configuration["bar"]?==?"xyz");var?app?=?builder.Build();
configuration?=?app.Configuration;
Debug.Assert(configuration["foo"]?==?"abc");
Debug.Assert(configuration["bar"]?==?"xyz");

[S1515]注冊配置源(利用IWebHostBuilder)

配置系統最大的特點是可以注冊不同的配置源。針對配置源的注冊同樣可以利用三種編程方式來實現,第一種就是利用WebApplicationBuilder的Host屬性返回的IHostBuilder對象,并調用其的ConfigureHostConfiguration和ConfigureAppConfiguration方法完成針對宿主和應用的配置,其中自然包含針對配置源的注冊。IWebHostBuilder接口也提供如下這個等效的ConfigureAppConfiguration方法。如代碼片段所示,該方法提供的參數是一個Action<WebHostBuilderContext, IConfigurationBuilder>委托,這意味著我們可以就承載上下文對配置做針對性設置。如果提供的設置與當前承載上下文無關,我們還可以調用另一個參數類型為Action<IConfigurationBuilder>的ConfigureAppConfiguration方法重載。

public?interface?IWebHostBuilder
{IWebHostBuilder?ConfigureAppConfiguration(Action<WebHostBuilderContext,?IConfigurationBuilder>?configureDelegate);
}public?static?class?WebHostBuilderExtensions
{public?static?IWebHostBuilder?ConfigureAppConfiguration(this?IWebHostBuilder?hostBuilder,?Action<IConfigurationBuilder>?configureDelegate);
}

我們可以利用WebApplicationBuilder的WebHost屬性返回對應的IWebHostBuilder對象,并采用如下的方式利用這個對象注冊配置源。

using?System.Diagnostics;var?builder?=?WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureAppConfiguration(config?=>?config.AddInMemoryCollection(new?Dictionary<string,?string>{["foo"]?=?"123",["bar"]?=?"456"}));
var?app?=?builder.Build();
Debug.Assert(app.Configuration["foo"]?==?"123");
Debug.Assert(app.Configuration["bar"]?==?"456");

[S1516]注冊配置源(Minimal API)

由于WebApplicationBuilder的Configuration屬性返回的ConfigurationManager自身就是一個IConfigurationBuilder對象,所以最直接的方式就是按照如下的方式將配置源注冊到它上面,這也是我們提供的編程方式。值得一提的是,如果調用WebApplication類型的CreateBuilder或者Create方法時傳入了命令行參數,會自動添加針對命令行參數的配置源。

using?System.Diagnostics;var?builder?=?WebApplication.CreateBuilder(args);
builder.Configuration.AddInMemoryCollection(new?Dictionary<string,?string>
{["foo"]?=?"123",["bar"]?=?"456"
});
var?app?=?builder.Build();
Debug.Assert(app.Configuration["foo"]?==?"123");
Debug.Assert(app.Configuration["bar"]?==?"456");

[S1517]默認的承載環境

如下面的代碼片段所示,派生于IHostEnvironment接口的IWebHostEnvironment接口定義了WebRootPath和WebRootFileProvider屬性,前者表示用于存放Web資源文件根目錄的路徑,后者則返回該路徑對應的IFileProvider對象。如果我們希望外部可以采用HTTP請求的方式直接訪問某個靜態文件(如JavaScript、CSS和圖片文件等),只需要將它存放于WebRootPath屬性表示的目錄之下即可。當前承載環境之間反映在WebApplicationBuilder類型如下所示的Environment屬性中。代表承載應用的WebApplication類型同樣具有這樣一個屬性。

public?interface?IWebHostEnvironment?:?IHostEnvironment
{string?WebRootPath?{?get;?set;?}IFileProvider?WebRootFileProvider?{?get;?set;?}
}public?sealed?class?WebApplicationBuilder
{public?IWebHostEnvironment?Environment?{?get;?}...
}public?sealed?class?WebApplication
{public?IWebHostEnvironment?Environment?{?get;?}...
}

我們簡單介紹與承載環境相關的六個屬性(包含定義在IHostEnvironment接口中的四個屬性)是如何設置的。IHostEnvironment 接口的ApplicationName代表當前應用的名稱,它的默認值為入口程序集的名稱。EnvironmentName表示當前應用所處部署環境的名稱,其中開發(Development)、預發(Staging)和產品(Production)是三種典型的部署環境。根據不同的目的可以將同一個應用部署到不同的環境中,在不同環境中部署的應用往往具有不同的設置。在默認情況下,環境的名稱為“Production”。ASP.NET Core應用會將所有的內容文件存儲在同一個目錄下,這個目錄的絕對路徑通過IWebHostEnvironment接口的ContentRootPath屬性來表示,而ContentRootFileProvider屬性則返回針對這個目錄的PhysicalFileProvider對象。部分內容文件可以直接作為Web資源(如JavaScript、CSS和圖片等)供客戶端以HTTP請求的方式獲取,存放此種類型內容文件的絕對目錄通過IWebHostEnvironment接口的WebRootPath屬性來表示,而針對該目錄的PhysicalFileProvider自然可以通過對應的WebRootFileProvider屬性來獲取。

在默認情況下,由ContentRootPath屬性表示的內容文件的根目錄就是當前工作目錄。如果該目錄下存在一個名為“wwwroot”的子目錄,那么它將用來存放Web資源,WebRootPath屬性將返回這個目錄。如果這樣的子目錄不存在,那么WebRootPath屬性會返回Null。針對這兩個目錄的默認設置體現在如下所示的代碼片段中。

using?System.Diagnostics;
using?System.Reflection;var?builder?=?WebApplication.CreateBuilder();
var?environment?=?builder.Environment;Debug.Assert(Assembly.GetEntryAssembly()?.GetName().Name?==?environment.ApplicationName);
var?currentDirectory?=?Directory.GetCurrentDirectory();Debug.Assert(Equals(?environment.ContentRootPath,??currentDirectory));
Debug.Assert(Equals(environment.ContentRootPath,?currentDirectory));var?wwwRoot?=?Path.Combine(currentDirectory,?"wwwroot");
if?(Directory.Exists(wwwRoot))
{Debug.Assert(Equals(environment.WebRootPath,?wwwRoot));
}
else
{Debug.Assert(environment.WebRootPath?==?null);
}static?bool?Equals(string?path1,?string?path2)?=>string.Equals(path1.Trim(Path.DirectorySeparatorChar),?path2.Trim(Path.DirectorySeparatorChar),StringComparison.OrdinalIgnoreCase);

[S1518]通過配置定制承載環境

IWebHostEnvironment對象承載的與承載環境相關的屬性(ApplicationName、EnvironmentName、ContentRootPath和WebRootPath)可以通過配置的方式進行定制,對應配置項的名稱分別為“applicationName”、“environment”、“contentRoot”和“webroot”。靜態類WebHostDefaults為它們定義了對應的屬性。前三個配置項的名稱同樣以靜態只讀字段的形式定義在HostDefaults類型中。

public?static?class?WebHostDefaults
{public?static?readonly?string?EnvironmentKey?=?"environment";public?static?readonly?string?ContentRootKey?=?"contentRoot";public?static?readonly?string?ApplicationKey?=?"applicationName";public?static?readonly?string?WebRootKey?=?"webroot";;
}public?static?class?HostDefaults
{public?static?readonly?string?EnvironmentKey?=?"environment";public?static?readonly?string?ContentRootKey?=?"contentRoot";public?static?readonly?string?ApplicationKey?=?"applicationName";
}

由于應用初始化過程中的很多操作都與當前的承載環境有關,所以承載環境必須在啟動應用最初的環境就被確定下來,并在整個應用生命周期內都不能改變。如果我們希望采用配置的方式來控制當前應用的承載環境,相應的設置必須在WebApplicationBuilder對象創建之前執行,在之后試圖修改相關的配置都會拋出異常。按照這個原則,我們可以采用命令行參數的方式對承載環境進行設置。

var?app?=?WebApplication.Create(args);
var?environment?=?app.Environment;Console.WriteLine($"ApplicationName:{environment.ApplicationName}");
Console.WriteLine($"ContentRootPath:{environment.ContentRootPath}");
Console.WriteLine($"WebRootPath:{environment.WebRootPath}");
Console.WriteLine($"EnvironmentName:{environment.EnvironmentName}");

上面的演示程序利用命令行參數的方式控制承載環境的四個屬性。如代碼片段所示,我們將命令行參數傳入WebApplication類型的Create方法創建了一個WebApplication對象,然后從中提取出代表承載環境的IWebHostEnvironment對象并將其攜帶信息輸出到控制臺上。我們命令行的方式啟動該程序,并指定了與承載環境相關的四個參數。

c7767b8db10ab0cfd010a23f076274b9.png
圖1 利用命令行參數定義承載環境

除了命令行參數,使用環境變量同樣能達到相同的目的,應用的名稱目前無法通過對應的配置進行設置。對于上面創建的這個演示程序,我們現在換一種方式啟動它。如圖2所示,在執行“dotnet run”命令啟動程序之前,我們為承載環境的四個屬性設置了對應的環境變量。從輸出的結果可以看出,除了應用名稱依然是入口程序集名稱外,承載環境的其他三個屬性與我們設置的環境變量是一致的。

5e1430736a7e4b0fb1c7f635b24a0ea0.png
圖2 利用環境變量定義承載環境

[S1519]利用WebApplicationOptions定制承載環境

承載環境除了可以采用利用上面演示的兩種方式進行設置外,我們也可以使用如下這個WebApplicationOptions配置選項。如代碼片段所示,WebApplicationOptions定義了四個屬性,分別代表命令行參數數組、環境名稱、應用名稱和內容根目錄路徑。WebApplicationBuilder具有如下這個參數類型為WebApplicationOptions的CreateBuilder方法。

public?class?WebApplicationOptions
{public?string[]?Args?{?get;?set;?}public?string?EnvironmentName?{?get;?set;?}public?string?ApplicationName?{?get;?set;?}public?string?ContentRootPath?{?get;?set;?}
}public?sealed?class?WebApplication
{public?static?WebApplicationBuilder?CreateBuilder(WebApplicationOptions?options);...
}

如果利用WebApplicationOptions來對應用所在的承載環境進行設置,上面演示的程序可以改寫成如下的形式。由于WebApplicationOptions并不包含WebRootPath對應的配置選項,如果程序運行后會發現承載環境的這個屬性為空。由于IWebHostEnvironment服務提供的應用名稱會被視為一個程序集名稱,針對它的設置會影響類型的加載,所以我們基本上不會設置應用的名稱。

var?options?=?new?WebApplicationOptions
{Args?=?args,ApplicationName?=?"MyApp",ContentRootPath?=?Path.Combine(Directory.GetCurrentDirectory(),?"contents"),EnvironmentName?=?"staging"
};
var?app?=?WebApplication.CreateBuilder(options).Build();
var?environment?=?app.Environment;
Console.WriteLine($"ApplicationName:{environment.ApplicationName}");
Console.WriteLine($"ContentRootPath:{environment.ContentRootPath}");
Console.WriteLine($"WebRootPath:{environment.WebRootPath}");
Console.WriteLine($"EnvironmentName:{environment.EnvironmentName}");

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282875.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282875.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282875.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

oracle的除,Oracle數據庫如何去除別名 - daiyan0526的個人空間 - 51Testing軟件測試網 51Testing軟件測試網-軟件測試人的精神家園...

本人曾經用Personal OracleDeveloper2000開發了一些程序&#xff0c;當移植到FOR NT的時候發現有些功能出現了出錯提示。經研究發現原來是用戶沒有能正常連接。由于在developer2000連接personal oracle時不需要別名(alias)&#xff0c;直接寫入用戶名/密碼則可。而在OracleFOR …

Java 之 JavaScript (一)

1.JavaScripta.定義&#xff1a;JavaScript是腳本語言&#xff0c;是一種輕量級的編程語言b.實現&#xff1a;①直接通過標簽里面的onXX屬性驅動js的執行<input type"button" value"測試" οnclick"alert(‘hello‘)">②引入外部js文件——…

Linux日志出現大量kernel: NET: Registered protocol family 36

一臺Linux服務器的系統錯誤日志出現大量的“ kernel: NET: Registered protocol family 36”錯誤信息&#xff0c;如下所示&#xff1a; Jul 2 05:27:45 xxxxxx kernel: NET: Registered protocol family 36Jul 2 05:27:45 xxxxxx kernel: NET: Unregistered protocol family…

node的模塊機制

Node.js模塊的實現 之前在網上查閱了許多介紹Node.js的文章&#xff0c;可惜對于Node.js的模塊機制大都著墨不多。在后續介紹模塊的使用之前&#xff0c;我認為有必要深入一下Node.js的模塊機制。 CommonJS規范 早在Netscape誕生不久后&#xff0c;JavaScript就一直在探索本地編…

vs使用ado連接oracle,在VS環境下以ADO方式操作Oracle數據庫

利用ADO引擎方式訪問Oracle數據庫的實現方法&#xff1a;定義數據庫頭文件為CDBOperation.h#pragma once#import "C:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename("EOF","adoEOF"),rename("LockTypeEnum"…

httpstat:一個檢查網站性能的 curl 統計分析工具

httpstat&#xff1a;一個檢查網站性能的 curl 統計分析工具httpstat 是一個 Python 腳本&#xff0c;它以美妙妥善的方式反映了 curl 統計分析&#xff0c;它是一個單一腳本&#xff0c;兼容 Python 3 &#xff0c;在用戶的系統上不需要安裝額外的軟件(依賴)。作者&#xff1a…

Unity(創建腳本)

#一、描述 記錄第一課時&#xff0c;腳本的創建與使用基本的API #二、學習記錄 &#xff08;一&#xff09;創建一個Cube方塊 &#xff08;二&#xff09;在cube組件上添加一個腳本&#xff0c;選中cube組件&#xff0c;在屏幕右側有著cube的組件屬性欄&#xff0c;點擊AddComp…

關于面試中看到一些問題

最近公司在招聘.NET開發人員&#xff0c;面試了一些人&#xff0c;有一些感悟&#xff0c;分享出來&#xff0c;以供參考。面試的人員中&#xff0c;有一些是三五年的開發人員&#xff1b;也有幾個是10年左右的技術負責人&#xff0c;不但自己架構過項目&#xff0c;還有帶領導…

jQuery遍歷not的用法

從包含所有段落的集合中刪除 id 為 "selected" 的段落&#xff1a; $("p").not("#selected") 定義和用法 not() 從匹配元素集合中刪除元素。 語法 1 .not(selector) 參數描述selector字符串值&#xff0c;包含用于匹配元素的選擇器表達式。語法 …

linux 字符串加入中括號,Linux Shell 基礎 -- 總結幾種括號、引號的用法

1、雙引號 " "雙引號常用于包含一組字符串&#xff0c;在雙引號中&#xff0c;除了 "$"、""、" (反引號)"有特殊含義外&#xff0c;其余字符(如IFS、換行符、回車符等)沒有特殊含義。$ a3$ echo "$a"輸出結果為 3&#xff…

設計模式相關

多例模式 轉載于:https://www.cnblogs.com/our880tom/p/6392983.html

一個countDown在多線程調度下使用不當的分享

2019獨角獸企業重金招聘Python工程師標準>>> 一個countDown在多線程調度下使用不當的分享 1. 詭異的數據抖動 在一個需求開發過程中&#xff0c;由于有多角色需要獲取每個角色下的菜單&#xff1b;結果出現了單角色下拉去菜單沒問題&#xff0c;多角色情況下只有一個…

我堅持三年了!

閱讀本文大概需要5分鐘。不知不覺&#xff0c;公眾號寫作已經持續了3年了。2019年11月底&#xff0c;心血來潮寫了第一篇文章&#xff0c;更多是為了復盤過去的一些工作經歷。在前幾天&#xff0c;讀者數突破了16萬&#xff0c;雖然這個數字相比那些頭部大號而言并不多&#xf…

關于Qt模態框總匯

轉載請注明出處&#xff1a;http://www.cnblogs.com/dachen408/p/7285710.html 父窗體為QMainWindow&#xff1b; 當子窗體為&#xff1a; 1.QWidget&#xff0c;需要設置 this->setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); this->setWindowModality(Qt::Win…

linux腳本打印循環次數,shell腳本編程基礎(3)——循環用法

本節索引&#xff1a;一、if、case條件判斷二、for、while及until循環三、循環控制語句continue、break、shift及select菜單四、信號捕捉trap在前面的基礎編程內容中&#xff0c;我們已經學習了shell腳本的順序執行及選擇執行&#xff0c;通過這兩種方式&#xff0c;可以幫我們…

RTSP服務器之————rtsp-server(輕量級RTSP / RTP流媒體服務器)

github&#xff1a;https://github.com/revmischa/rtsp-server 輕量級RTSP / RTP流媒體服務器

EF CORE 7 中的新功能:使用 ExecuteDelete 和 ExecuteUpdate 進行批量操作

原文鏈接&#xff1a;https://timdeschryver.dev/blog/new-in-entity-framework-7-bulk-operations-with-executedelete-and-executeupdate原文作者&#xff1a;tim_deschryver翻譯&#xff1a;沙漠盡頭的狼(谷歌翻譯加持)Entity Framework 7 包括一些已被要求的流行功能&#…

java 簡單json和對象相互轉換

2019獨角獸企業重金招聘Python工程師標準>>> package Fasterxml; import com.fasterxml.jackson.databind.ObjectMapper; import mode.User; import java.io.StringWriter; import java.util.ArrayList; import java.util.List;/*** maven...**<dependency>* …

暢想動畫制作的樂趣

為什么要制作動畫&#xff1f; 現在的營銷活動&#xff0c;用一個很簡單的圖片去吸引消費者已經遠遠不夠。想讓消費者創造GMV&#xff0c;肯定需要讓消費者覺得眼前一亮或是有視覺沖擊的東西&#xff0c;或者在動畫過程中提供更好的引導部分&#xff0c;比如紅包&#xff0c;引…

Linux的scan命令,linux的scan命令

linux下scan命令主要是以scanf的形式使用轉換符解析字符串&#xff0c;下面由秋天網 Qiutian.ZqNF.Com小編為大家整理了linux下scan命令的相關知識&#xff0c;希望對大家有幫助!linux的scan命令詳解scan - 以sscanf的形式使用轉換符解析字符串語法:scan string format ?varna…