在ASP.NET Core中的App configuration 是經過configuration providers基於key-value對創建的。Configuration providers讀取配置文件到key-value,從多種配置源中:html
用於提供Configuration配置的包是包含在Microsoft.AspNetCore.App metapackage裏。下面的代碼示例,將會使用Microsoft.Extensions.Configuration命名空間。數據庫
using Microsoft.Extensions.Configuration;
1.Host vs App configuration(對比)json
在應用配置和啓動以前,host被配置和launched(發動,開展)。Host 負責應用的startup和生命週期管理。應用和主機都是用這個主題描述的configuration providers來配置。主機配置的key-values對成爲應用全局配置的一部分。api
2.Default configuration數組
ASP.NET Core基礎上的Web應用 dotnet new templates(模板)會調用CreateDefaultBuilder,當創建host時,CreateDefaultBuilder爲應用提供默認的配置,以下面的順序:瀏覽器
(1).主機配置是被下面這些提供的:數據結構
(2).應用配置是被下面這些提供的:app
3.Securityide
採用下面的最佳實踐:函數
4.Hierarchical configuration data(分層的配置數據)
在下面的JSON文件中,結構化分層的兩個sections中存在四個key:
{ "section0": { "key0": "value", "key1": "value" }, "section1": { "key0": "value", "key1": "value" } }
當文件被讀取到配置中時,惟一的key被建立,來維護原始配置源中的分層數據結構。
Section和key被使用冒號展開來維持原始結構:
section0:key0
section0:key1
section1:key0
section1:key1
如上,每一個值均可以被惟一的取到。
GetSection和GetChildren方法能夠被用來分離配置數據中的sections和section的children 。這些方法會在隨後的GetSection,GetChildren,和Exists描述。GetSection是在Microsoft.Extensions.Configuration包中,這個包是在Microsoft.AspNetCore.App metapackage.
5.Conventions(習慣,約定)
這裏是一些習慣的約定。
在應用啓動時,配置源按照它們的configuration provider被指定的順序來被讀取。
Configuration providers實現了變化檢測,Configuration providers能夠從新加載配置,當一個基礎的設置被改變時。例如,File Configuration Provider和Azure key Value Configuration Provider實現了變化檢測。
IConfiguration在應用的依賴注入(DI)容器中是可用的。IConfiguration能夠被注入到一個Razor Pages Pagemodel來包含一個配置的類。
public class IndexModel : PageModel { private readonly IConfiguration _config; public IndexModel(IConfiguration config) { _config = config; } // The _config local variable is used to obtain configuration // throughout the class. }
Configuration providers不能使用DI,由於當它們(Configuration providers)被host創建時,DI是不可用的。
Configuration keys採用下面的約定:
Configuratian values採用下面的約定:
6.Providers
下面列出了ASP.NET Core應用可用的configuration providers:
Configuration sources(配置源)按照它們的configuration providers在startup中指定的順序被順序讀取。
典型的configuration providers的順序:
這是一種通用的實踐,把命令行配置源放到最後,使它能夠重寫其餘配置源設置的配置。
注意:後面的配置會覆蓋前面的配置
7.ConfigureAppConfiguration
調用ConfigureAppConfiguration,當須要創建host來指定除了被CreateDefaultBuilder自動添加配置源外的其餘配置源:
public class Program { public static Dictionary<string, string> arrayDict = new Dictionary<string, string> { {"array:entries:0", "value0"}, {"array:entries:1", "value1"}, {"array:entries:2", "value2"}, {"array:entries:4", "value4"}, {"array:entries:5", "value5"} }; public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.SetBasePath(Directory.GetCurrentDirectory()); config.AddInMemoryCollection(arrayDict); config.AddJsonFile( "json_array.json", optional: false, reloadOnChange: false); config.AddJsonFile( "starship.json", optional: false, reloadOnChange: false); config.AddXmlFile( "tvshow.xml", optional: false, reloadOnChange: false); config.AddEFConfiguration( options => options.UseInMemoryDatabase("InMemoryDb")); config.AddCommandLine(args); }) .UseStartup<Startup>(); }
8.Command-line Configuration Provider
在運行時,CommandLineConfigurationProviders從command line argument key-value pairs中加載配置.
要想啓動command-line 配置,AddCommandLine擴展方法須要在ConfigurationBuilder實例中被調用。
AddCommandLine早已被CreateDefaultBuilder調用。若是你須要提供 app configuration 而且仍然能夠用command-line arguments重寫配置,在ConfigureAppConfiguration中,調用app的額外的providers,而且在最後調用AddCommandLine.
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { // Call other providers here and call AddCommandLine last. config.AddCommandLine(args); }) .UseStartup<Startup>(); }
當直接建立一個WebHostBuilder時,調用UseConfiguration(另外一種用法):
var config = new ConfigurationBuilder() // Call additional providers here as needed. // Call AddCommandLine last to allow arguments to override other configuration. .AddCommandLine(args) .Build(); var host = new WebHostBuilder() .UseConfiguration(config) .UseKestrel() .UseStartup<Startup>();
Example
示例應用功能利用靜態方法CreateDefaultBuilder來創建host,它包含對AddCommandLine的調用.
Arguments
值必須是下面的形式.=後面的值能夠爲null(例如,CommandLineKey=)
在同一個命令窗口中,不要混合使用=號和空格
dotnet run CommandLineKey1=value1 --CommandLineKey2=value2 /CommandLineKey3=value3 dotnet run --CommandLineKey1 value1 /CommandLineKey2 value2 dotnet run CommandLineKey1= CommandLineKey2=value2
Switch mappings
Switch mapping dictionary key rules:
當創建host指定應用配置時,調用ConfigureAppConfiguration:
public class Program { public static readonly Dictionary<string, string> _switchMappings = new Dictionary<string, string> { { "-CLKey1", "CommandLineKey1" },//把命令行中key爲-CLKey1的鍵替換爲key爲CommandLineKey1 { "-CLKey2", "CommandLineKey2" } }; public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } // Do not pass the args to CreateDefaultBuilder public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder() .ConfigureAppConfiguration((hostingContext, config) => { config.AddCommandLine(args, _switchMappings); }) .UseStartup<Startup>(); }
當switch mappings dictionary被建立後,包含下面的數據:
若是啓動應用時,switch-mapped keys被使用,configuration會在dictionary提供的key裏接收到配置值。
dotnet run -CLKey1=value1 -CLKey2=value2
在運行以前的命令後,configuration包含了值,以下表:
如上,能夠看出Switch mappings的做用是:
把命令行中輸入的key替換爲switch mapping中的key值。
9.Environment Variables Configuration Provider
要啓用environment variables configuration,須要調用AddEnvironmentVariables擴展方法。
AddEnvironmentVariables用來加載以ASPNETCORE_開頭的環境變量。
當創建host指定應用配置時,調用ConfigureAppConfiguration :
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { // Call additional providers here as needed. // Call AddEnvironmentVariables last if you need to allow // environment variables to override values from other // providers. config.AddEnvironmentVariables(prefix: "PREFIX_"); }) .UseStartup<Startup>(); }
當直接建立WebHostBuilder,調用UseConfiguration:
var config = new ConfigurationBuilder() .AddEnvironmentVariables() .Build(); var host = new WebHostBuilder() .UseConfiguration(config) .UseKestrel() .UseStartup<Startup>();
Example
示例應用功能利用靜態方法CreateDefaultBuilder來創建host,它包含對AddEnvironmentVariables的調用.
環境變量如下面的開頭:
若是你但願在應用中暴露這些環境變量可用,在Pages/Index.cshtml.cs中改變FilteredConfiguration爲下面:
FilteredConfiguration = _config.AsEnumerable();
Prefixes
當你應用一個前綴到AddEnvironmentVariables方法,應用配置中的環境變量能夠被過濾。例如,在前綴CUSTOM_上過濾環境變量,應用前綴到configuration provider:
var config = new ConfigurationBuilder() .AddEnvironmentVariables("CUSTOM_") .Build();
前綴會被分離,當配置key-values pairs被建立時。
靜態方法CreateDefaultBuilder會建立一個WebHostBuilder來創建應用主機。當WebHostBuilder被建立時,能夠在環境變量中找到ASPNETCORE_爲前綴的主機配置。
(1).Connection string prefixes
Configuration API(配置api)對於四個鏈接字符串環境變量有特殊的處理規則。若是沒有前綴做用到AddEnvironmentVariables,帶有下面前綴的環境變量會被加載到應用中
當一個環境變量被發現,而且帶有上面四個之一的前綴被加載到配置:
10.File Configuration Provider
FileConfigurationProvider是從文件系統中加載配置的基礎類。下面的configuration providers是做用特定的文件類型:
INI Configuration Provider
IniConfigurationProvider從INI文件中加載配置。
要啓用INI 文件配置,在ConfigurationBuilder實例中調用AddIniFile擴展方法。
重寫一些指定配置選項:
調用ConfigureAppConfiguration,當創建host指定應用配置時:
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.SetBasePath(Directory.GetCurrentDirectory()); config.AddIniFile( "config.ini", optional: true, reloadOnChange: true); }) .UseStartup<Startup>(); }
基礎路徑(base path)是經過SetBasePath設置。SetBasePath是在Microsoft.Extensions.Configuration.FileExtension包中,這個包是在Microsoft.AspNetCore.App metapackage.
當直接建立一個WebHostBuilder,調用UseConfiguration:
var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddIniFile("config.ini", optional: true, reloadOnChange: true) .Build(); var host = new WebHostBuilder() .UseConfiguration(config) .UseKestrel() .UseStartup<Startup>();
一個INI configuration file示例:
[section0] key0=value key1=value [section1] subsection:key=value [section2:subsection0] key=value [section2:subsection1] key=value
上面的配置文件加載下面的key和value:
JSON Configuration Provider
JsonConfigurationProvider從JSON文件中加載配置.
要啓用JSON文件配置,在ConfigurationBuilder實例上,調用AddJsonFile擴展方法。
重寫一些指定配置選項:
AddJsonFile會自動調用兩次,當你用CreateDefaultBuilder初始化一個WebHostBuilder時。這個方法被調用加載配置,從下面的:
調用ConfiureAppConfiguration,當創建host來指定應用配置,經過其餘文件而不是經過appsettings.json和appsettings.{Environment}.json文件。
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.SetBasePath(Directory.GetCurrentDirectory()); config.AddJsonFile( "config.json", optional: true, reloadOnChange: true); }) .UseStartup<Startup>(); }
當直接建立WebHostBuilder,調用UseConfiguration:
var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("config.json", optional: true, reloadOnChange: true) .Build(); var host = new WebHostBuilder() .UseConfiguration(config) .UseKestrel() .UseStartup<Startup>();
Example
示例應用利用靜態方法CreateDefaultBuilder來創建host,它包含兩次對AddJsonFile的調用。配置從appsettings.json和appsettings.{Environment}.json文件中加載
XML Configuration Provider
XmlConfigurationProvider從XML文件中加載配置。
要啓用XML文件配置,在ConfigurationBuilder實例上調用AddXmlFile擴展方法。
配置文件的根節點被忽略了,當配置key-value pairs被建立了。不要在文件中指定一個Document Type Definition(DTD)或者命名空間。
調用ConfigureAppConfiguration,當創建host來指定應用的配置時:
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.SetBasePath(Directory.GetCurrentDirectory()); config.AddXmlFile( "config.xml", optional: true, reloadOnChange: true); }) .UseStartup<Startup>(); }
當直接建立WebHostBuilder,調用UseConfiguration:
var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddXmlFile("config.xml", optional: true, reloadOnChange: true) .Build(); var host = new WebHostBuilder() .UseConfiguration(config) .UseKestrel() .UseStartup<Startup>();
(1).XML配置文件能夠使用distinct元素名稱對於repeating sections:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <section0> <key0>value</key0> <key1>value</key1> </section0> <section1> <key0>value</key0> <key1>value</key1> </section1> </configuration>
前面的配置文件在家下面的key和value:
(2).還能夠以下,用name屬性區分元素的形式:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <section name="section0"> <key name="key0">value</key> <key name="key1">value</key> </section> <section name="section1"> <key name="key0">value</key> <key name="key1">value</key> </section> </configuration>
以前的配合文件加載下面的key和value:
(3).屬性也能夠用於值上:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <key attribute="value" /> <section> <key attribute="value" /> </section> </configuration>
以前的配置文件加載下面的key和value:
11.Key-per-file Configuration Provider
KeyPerFileConfigurationProvider使用一個目錄文件做爲configuration key-value pairs.其中key是文件名。 value包含文件內容。Key-per-file Configuration Provider用於Docker hosting 場景。
要啓用key-per-file configuration, 在ConfigurationBuilder實例上,調用AddKeyPerFile擴展方法。文件的目錄路徑(directoryPath)必須是絕對路徑。
Overloads permit specifying:
在文件名字中,雙下劃線(__)用做一個configuration key 分隔符。例如,文件名Logging__LogLevel__System產生configuration key : Logging:logLevel:System
調用ConfigureAppConfiguration,當創建host來指定應用的配置時:
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.SetBasePath(Directory.GetCurrentDirectory()); var path = Path.Combine( Directory.GetCurrentDirectory(), "path/to/files"); config.AddKeyPerFile(directoryPath: path, optional: true); }) .UseStartup<Startup>(); }
當直接建立WebHostBuilder時,調用UseConfiguration:
var path = Path.Combine(Directory.GetCurrentDirectory(), "path/to/files"); var config = new ConfigurationBuilder() .AddKeyPerFile(directoryPath: path, optional: true) .Build(); var host = new WebHostBuilder() .UseConfiguration(config) .UseKestrel() .UseStartup<Startup>();
12.Memory Configuration Provider
MemoryConfigurationProvider使用內存集合做爲配置key-value pairs.
要使用in-memory collection configuration,在ConfigurationBuilder實例上,調用AddInMemoryCollection擴展方法。
The configuration provider能夠使用IEnumerable<KeyValuePair<String,String>>來初始化。
當創建host來指定應用配置時,調用ConfigureAppConfiguration:
public class Program { public static readonly Dictionary<string, string> _dict = new Dictionary<string, string> { {"MemoryCollectionKey1", "value1"}, {"MemoryCollectionKey2", "value2"} }; public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddInMemoryCollection(_dict); }) .UseStartup<Startup>(); }
當直接建立WebHostBuilder時,調用UseConfiguration:
var dict = new Dictionary<string, string> { {"MemoryCollectionKey1", "value1"}, {"MemoryCollectionKey2", "value2"} }; var config = new ConfigurationBuilder() .AddInMemoryCollection(dict) .Build(); var host = new WebHostBuilder() .UseConfiguration(config) .UseKestrel() .UseStartup<Startup>();
13.GetValue
ConfigurationBinder.GetValue<T> 從配置文件中用特定的key提出value,而且轉化爲特定類型。若是這個key沒找到,能夠提供默認值。
下面的例子:
public class IndexModel : PageModel { public IndexModel(IConfiguration config) { _config = config; } public int NumberConfig { get; private set; } public void OnGet() { NumberConfig = _config.GetValue<int>("NumberKey", 99); } }
14.GetSection, GetChildren, and Exists
{ "section0": { "key0": "value", "key1": "value" }, "section1": { "key0": "value", "key1": "value" }, "section2": { "subsection0" : { "key0": "value", "key1": "value" }, "subsection1" : { "key0": "value", "key1": "value" } } }
當文件被讀取到配置中,以下:
GetSection
IConfiguration.GetSection用特定的subsection key提取一個configuration subsection.
要返回一個包含在section1中的key-value pairs的IConfigurationSection,調用GetSection而且應用section name:
var configSection = _config.GetSection("section1");
其中configSection沒有value,只有一個key和path.
類似的,要包含key爲section2:subsection0的value,調用GetSection而且應用section path:
var configSection = _config.GetSection("section2:subsection0");
GetSection不會返回null。 若是沒有匹配的section,一個空的IConfigurationSection會被返回。
GetChildren
調用在section2上的IConfiguration.GetChildren包含:
var configSection = _config.GetSection("section2"); var children = configSection.GetChildren();
Exists
用ConfigurationExtensions.Exists來肯定configuration section是否存在:
var sectionExists = _config.GetSection("section2:subsection2").Exists();
給出的例子中的數據,sectionExists是false,由於section2:subsection2這個section不存在。
15.Bind to a class
配置能夠被綁定到類中。
示例包含一個Startship的model(Models/Starship.cs):
public class Starship { public string Name { get; set; } public string Registry { get; set; } public string Class { get; set; } public decimal Length { get; set; } public bool Commissioned { get; set; } }
Starship.json文件中starship的section節建立了配置,當示例應用使用JSON Configuration Provider加載配置時。
{ "starship": { "name": "USS Enterprise", "registry": "NCC-1701", "class": "Constitution", "length": 304.8, "commissioned": false }, "trademark": "Paramount Pictures Corp. http://www.paramount.com" }
下面的配置被建立了:
示例應用利用key爲starship來調用GetSection。Starship key-value pairs被分離。在綁定實例值後:
var starship = new Starship(); _config.GetSection("starship").Bind(starship); Starship = starship;
16.Bind to an object graph
示例綁定一個TvShow的model,它包含Metadata和Actors類:
public class TvShow { public Metadata Metadata { get; set; } public Actors Actors { get; set; } public string Legal { get; set; } } public class Metadata { public string Series { get; set; } public string Title { get; set; } public DateTime AirDate { get; set; } public int Episodes { get; set; } } public class Actors { public string Names { get; set; } }
示例應用有個tvshow.xml文件包含配置數據:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <tvshow> <metadata> <series>Dr. Who</series> <title>The Sun Makers</title> <airdate>11/26/1977</airdate> <episodes>4</episodes> </metadata> <actors> <names>Tom Baker, Louise Jameson, John Leeson</names> </actors> <legal>(c)1977 BBC https://www.bbc.co.uk/programmes/b006q2x0</legal> </tvshow> </configuration>
配置被Bind方法綁定到了TvShow對象上。以下:
var tvShow = new TvShow(); _config.GetSection("tvshow").Bind(tvShow); TvShow = tvShow;
ConfigurationBinder.Get<T>綁定和返回指定的類型。Get<T>比使用Bind更方便。下面的代碼展現了怎麼再以前的代碼使用Get<T>,以下:
TvShow = _config.GetSection("tvshow").Get<TvShow>();
17.Bind an array to a c lass
Bind還支持綁定數組.
In-memory array processing
考慮下面配置中的keys和values:
示例應用中的keys和values被使用Memory Configuration Provider被加載:
public class Program { public static Dictionary<string, string> arrayDict = new Dictionary<string, string> { {"array:entries:0", "value0"}, {"array:entries:1", "value1"}, {"array:entries:2", "value2"}, {"array:entries:4", "value4"}, {"array:entries:5", "value5"} }; public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.SetBasePath(Directory.GetCurrentDirectory()); config.AddInMemoryCollection(arrayDict); config.AddJsonFile( "json_array.json", optional: false, reloadOnChange: false); config.AddJsonFile( "starship.json", optional: false, reloadOnChange: false); config.AddXmlFile( "tvshow.xml", optional: false, reloadOnChange: false); config.AddEFConfiguration( options => options.UseInMemoryDatabase("InMemoryDb")); config.AddCommandLine(args); }) .UseStartup<Startup>(); }
數組跳過了索引爲3的值。Configuration binder不能綁定null 值或者建立null entries在綁定對象中。
在示例中,一個類用來綁定配置數據:
public class ArrayExample { public string[] Entries { get; set; } }
配置數據被綁定到對象上:
var arrayExample = new ArrayExample(); _config.GetSection("array").Bind(arrayExample);
也能夠使用ConfigurationBinder.Get<T>:
ArrayExample = _config.GetSection("array").Get<ArrayExample>();
ArrayExample的實例,接收到配置中的數組數據:
在綁定對象中,索引爲3有的是array:4的值。
要處理這樣的狀況,能夠這樣,使用一個額外的JOSN Configuration Provider處理丟失的key-value pair, ArrayExample.Entries匹配完整的配置數組:
missing_value.json:
{ "array:entries:3": "value3" }
在ConfigureAppConfiguration中:
config.AddJsonFile("missing_value.json", optional: false, reloadOnChange:false);
下面的值會被加載到配置中:
若是ArrayExample類的實例是在JSON Configuration Provider包含索引3後被綁定,ArrayExample.Entries數組會包含這個值:
JSON array processing
若是JSON文件包含一個數組,配置keys被建立爲數組的索引。下面的配置文件中,subsection是一個數組:
{ "json_array": { "key": "valueA", "subsection": [ "valueB", "valueC", "valueD" ] } }
JSON Configuration Provider讀取配置數據到下面所列:
在示例應用中,下面的類用來綁定配置數據:
public class JsonArrayExample { public string Key { get; set; } public string[] Subsection { get; set; } }
在綁定後,JsonArrayExample.Key有值valueA,subsection的值存儲在Subsection屬性的數組中。
18.Custom configuration provider
示例應用說明怎麼建立一個基礎的configuration provider,它能夠使用Entity Framework從數據庫讀取數據。
provider有下面特徵:
定義個EFConfigurationValue實體來存儲數據庫中的配置數據。
Models/EFConfigurationValues.cs:
public class EFConfigurationValue { public string Id { get; set; } public string Value { get; set; } }
增長一個EFConfigurationContext來存儲和取得配置值。
EFConfigurationProvider/EFConfigurationContext.cs:
public class EFConfigurationContext : DbContext { public EFConfigurationContext(DbContextOptions options) : base(options) { } public DbSet<EFConfigurationValue> Values { get; set; } }
建立一個類實現IConfigurationSource.
EFConfigurationProvider/EFConfigurationSource.cs:
public class EFConfigurationSource : IConfigurationSource { private readonly Action<DbContextOptionsBuilder> _optionsAction; public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction) { _optionsAction = optionsAction; } public IConfigurationProvider Build(IConfigurationBuilder builder) { return new EFConfigurationProvider(_optionsAction); } }
建立一個自定義的configuration provider經過繼承ConfigurationProvider.這個configuration provider初始化數據庫,當它是空的時。
EFConfigurationProvider/EFConfigurationProvider.cs:
public class EFConfigurationProvider : ConfigurationProvider { public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction) { OptionsAction = optionsAction; } Action<DbContextOptionsBuilder> OptionsAction { get; } // Load config data from EF DB. public override void Load() { var builder = new DbContextOptionsBuilder<EFConfigurationContext>(); OptionsAction(builder); using (var dbContext = new EFConfigurationContext(builder.Options)) { dbContext.Database.EnsureCreated(); Data = !dbContext.Values.Any() ? CreateAndSaveDefaultValues(dbContext) : dbContext.Values.ToDictionary(c => c.Id, c => c.Value); } } private static IDictionary<string, string> CreateAndSaveDefaultValues( EFConfigurationContext dbContext) { // Quotes (c)2005 Universal Pictures: Serenity // https://www.uphe.com/movies/serenity var configValues = new Dictionary<string, string> { { "quote1", "I aim to misbehave." }, { "quote2", "I swallowed a bug." }, { "quote3", "You can't stop the signal, Mal." } }; dbContext.Values.AddRange(configValues .Select(kvp => new EFConfigurationValue { Id = kvp.Key, Value = kvp.Value }) .ToArray()); dbContext.SaveChanges(); return configValues; } }
一個AddEFConfiguration擴展方法容許增長配置源到一個ConfigurationBuilder.
Extensions/EntityFrameworkExtension.cs:
public static class EntityFrameworkExtensions { public static IConfigurationBuilder AddEFConfiguration( this IConfigurationBuilder builder, Action<DbContextOptionsBuilder> optionsAction) { return builder.Add(new EFConfigurationSource(optionsAction)); } }
下面的代碼展現了怎麼在Program.cs中使用自定義的EFConfigurationProvider:
public class Program { public static Dictionary<string, string> arrayDict = new Dictionary<string, string> { {"array:entries:0", "value0"}, {"array:entries:1", "value1"}, {"array:entries:2", "value2"}, {"array:entries:4", "value4"}, {"array:entries:5", "value5"} }; public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.SetBasePath(Directory.GetCurrentDirectory()); config.AddInMemoryCollection(arrayDict); config.AddJsonFile( "json_array.json", optional: false, reloadOnChange: false); config.AddJsonFile( "starship.json", optional: false, reloadOnChange: false); config.AddXmlFile( "tvshow.xml", optional: false, reloadOnChange: false); config.AddEFConfiguration( options => options.UseInMemoryDatabase("InMemoryDb")); config.AddCommandLine(args); }) .UseStartup<Startup>(); }
在Startup.ConfigureServices中注入IConfiguration到Startup構造函數中來取得配置數據。要再Startup.Configure中取得配置數據,要麼直接注入IConfiguration到方法中,要麼使用構造函數中的實例:
public class Startup { private readonly IConfiguration _config; public Startup(IConfiguration config) { _config = config; } public void ConfigureServices(IServiceCollection services) { var value = _config["key"]; } public void Configure(IApplicationBuilder app, IConfiguration config) { var value = config["key"]; } }
20.Access configuration in a Razor Pages page or MVC view
在Razor Pages page或者MVC view中取得configuration settings.增長一個using指令爲Microsoft.Extensions.Configuration 命名空間,而且把IConfiguration注入到page或者view中。
在Razor Pages page:
@page @model IndexModel @using Microsoft.Extensions.Configuration @inject IConfiguration Configuration <!DOCTYPE html> <html lang="en"> <head> <title>Index Page</title> </head> <body> <h1>Access configuration in a Razor Pages page</h1> <p>Configuration value for 'key': @Configuration["key"]</p> </body> </html>
在MVC view中:
@using Microsoft.Extensions.Configuration @inject IConfiguration Configuration <!DOCTYPE html> <html lang="en"> <head> <title>Index View</title> </head> <body> <h1>Access configuration in an MVC view</h1> <p>Configuration value for 'key': @Configuration["key"]</p> </body> </html>
參考網址:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.2