《10分鐘就能學(xué)會(huì).NET Core配置》里詳細(xì)介紹了.NET Core配置的用法,另外我還開(kāi)源了自定義的配置Provider:EF配置Provider和Yaml配置Provider。本文先來(lái)聊聊EF配置Provider的實(shí)現(xiàn),其中會(huì)涉及到EntityFramework Core的知識(shí),不熟悉也沒(méi)關(guān)系,且聽(tīng)我慢慢講來(lái)。
配置執(zhí)行流程
在使用配置的時(shí)候都是先new ConfigurationBuilder()
,最后調(diào)用Build()
方法賦值給Configuration
屬性。那我們就從這個(gè)Build方法說(shuō)起。
Build方法做了什么呢,它遍歷了所有的配置源,等等,配置源哪來(lái)的?還記不記得AddJsonFile
,AddCommandLine
這些擴(kuò)展方法,它們做的事情就是將配置源添加到ConfigurationBuild中。每個(gè)配置源都有一個(gè)Build方法,它返回一個(gè)Provider。遍歷所有配置源時(shí)調(diào)用配置源的Build方法,就獲得了所有配置源的Provider,最后通過(guò)構(gòu)造函數(shù)傳給ConfigurationRoot
。
每個(gè)Provider里都有一個(gè)Load
方法,ConfigurationRoot的構(gòu)造函數(shù)會(huì)遍歷所有的Provider,調(diào)用它的Load方法。Load方法里需要做的就是把配置源里的配置轉(zhuǎn)換為IDictionary<string,string>
。
了解了配置執(zhí)行的流程,就可以動(dòng)手實(shí)現(xiàn)自己的Provider了。
EF存儲(chǔ)
Json配置Provider的配置存儲(chǔ)在Json文件中,基于EF的Provider的配置則是存儲(chǔ)在數(shù)據(jù)庫(kù)中,因?yàn)槭褂昧薊F,我們不需要關(guān)心使用的是什么數(shù)據(jù)庫(kù)。
在數(shù)據(jù)庫(kù)中存儲(chǔ)配置不支持嵌套和數(shù)組,只是簡(jiǎn)單的鍵值對(duì)形式,對(duì)應(yīng)數(shù)據(jù)庫(kù)表中的兩列。使用EF,需要先定義一個(gè)實(shí)體存儲(chǔ)配置,它包含兩個(gè)屬性,對(duì)應(yīng)數(shù)據(jù)庫(kù)表中的兩列。
internal class Configuration{ public string Key { get; set; } public string Value { get; set; } }
接著需要定義一個(gè)ConfigurationDbContext
用于存儲(chǔ)和訪(fǎng)問(wèn)配置。
internal class ConfigurationDbContext : DbContext{ private EFConfigurationOptionsBuilder Builder { get; } public ConfigurationDbContext(EFConfigurationOptionsBuilder options) : base(options.DbContextOptions.Options) { Builder = options; } public DbSet<Configuration> Configurations { get; set; } }
EFConfigurationOptionsBuilder
是自定義的類(lèi),它包含2個(gè)屬性,一個(gè)用于指定存儲(chǔ)配置表的名稱(chēng),另一個(gè)用于配置數(shù)據(jù)庫(kù)連接及其他配置。
EFConfigurationProvider
自定義Provider可繼承ConfigurationProvider
實(shí)現(xiàn)。在ConfigurationProvider中Load是一個(gè)虛方法,自定義Provider需要實(shí)現(xiàn)Load方法。
internal class EFConfigurationProvider : ConfigurationProvider{ Action<EFConfigurationOptionsBuilder> OptionsAction { get; } public EFConfigurationProvider(Action<EFConfigurationOptionsBuilder> optionsAction) { OptionsAction = optionsAction; } public override void Load() { var builder = new EFConfigurationOptionsBuilder(); OptionsAction(builder); using (var ctx = new ConfigurationDbContext(builder)) { ctx.Database.EnsureCreated(); Data = ctx.Configurations.ToDictionary(t => t.Key, t => t.Value); } } }
EFConfigurationSource
EFConfigurationSource繼承IConfigurationSource
,實(shí)現(xiàn)了Build方法,在Build中返回EFConfigurationProvider。
internal class EFConfigurationSource : IConfigurationSource{ private readonly Action<EFConfigurationOptionsBuilder> _optionsAction; public EFConfigurationSource(Action<EFConfigurationOptionsBuilder> optionsAction) { _optionsAction = optionsAction; } public IConfigurationProvider Build(IConfigurationBuilder builder) { return new EFConfigurationProvider(_optionsAction); } }
AddEntityFramework擴(kuò)展方法
為添加EF配置源增加一個(gè)擴(kuò)展方法。
public static class EFConfigurationExtensions{ public static IConfigurationBuilder AddEntityFramework(this IConfigurationBuilder builder, Action<EFConfigurationOptionsBuilder> setup) { return builder.Add(new EFConfigurationSource(setup)); } }
使用EF配置Provider
var builder = new ConfigurationBuilder() .AddEntityFramework(options => { options.TableName = "configs"; // 這里使用SQLite作為演示 options.DbContextOptions.UseSqlite("Filename=config.db"); }); Configuration = builder.Build();
上面我使用SQLite演示,也可以使用SQL Server、MySql、PostgreSQL等。默認(rèn)配置表的名稱(chēng)為Configuration。
最后
本項(xiàng)目已在github上開(kāi)源,地址:https://github.com/chengxulvtu/Cxlt.Extensions.Configuration
在項(xiàng)目中使用可以執(zhí)行下面的命令
Install-Package Cxlt.Extensions.Configuration.EF
或
dotnet add package Cxlt.Extensions.Configuration.EF
下篇文章《實(shí)現(xiàn)自己的.NET Core配置Provider之Yaml》將講解Yaml配置Provider的細(xì)節(jié)。
如果這篇文章對(duì)你有幫助,請(qǐng)點(diǎn)贊支持一下,也歡迎關(guān)注“chengxulvtu"公眾號(hào)。
作者:BobTian
出處:http://nianming.cnblogs.com/
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
歡迎訪(fǎng)問(wèn)我的個(gè)人博客:程序旅途
http://www.cnblogs.com/nianming/p/7092652.html