實現自己的.NET Core配置Provider之EF
《10分鐘就能學會.NET Core配置》裡詳細介紹了.NET Core配置的用法,另外我還開源了自定義的配置Provider:EF配置Provider和Yaml配置Provider。本文先來聊聊EF配置Provider的實現,其中會涉及到EntityFramework Core的知識,不熟悉也沒關係,且聽我慢慢講來。
配置執行流程
在使用配置的時候都是先new ConfigurationBuilder()
,最後呼叫Build()
方法賦值給Configuration
屬性。那我們就從這個Build方法說起。
Build方法做了什麼呢,它遍歷了所有的配置源,等等,配置源哪來的?還記不記得AddJsonFile
AddCommandLine
這些擴充套件方法,它們做的事情就是將配置源新增到ConfigurationBuild中。每個配置源都有一個Build方法,它返回一個Provider。遍歷所有配置源時呼叫配置源的Build方法,就獲得了所有配置源的Provider,最後通過建構函式傳給ConfigurationRoot
。
每個Provider裡都有一個Load
方法,ConfigurationRoot的建構函式會遍歷所有的Provider,呼叫它的Load方法。Load方法裡需要做的就是把配置源裡的配置轉換為IDictionary<string,string>
。
瞭解了配置執行的流程,就可以動手實現自己的Provider了。
EF儲存
Json配置Provider的配置儲存在Json檔案中,基於EF的Provider的配置則是儲存在資料庫中,因為使用了EF,我們不需要關心使用的是什麼資料庫。
在資料庫中儲存配置不支援巢狀和陣列,只是簡單的鍵值對形式,對應資料庫表中的兩列。使用EF,需要先定義一個實體儲存配置,它包含兩個屬性,對應資料庫表中的兩列。
internal class Configuration
{
public string Key { get; set; }
public string Value { get; set; }
}
接著需要定義一個ConfigurationDbContext
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
是自定義的類,它包含2個屬性,一個用於指定儲存配置表的名稱,另一個用於配置資料庫連線及其他配置。
EFConfigurationProvider
自定義Provider可繼承ConfigurationProvider
實現。在ConfigurationProvider中Load是一個虛方法,自定義Provider需要實現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
,實現了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擴充套件方法
為新增EF配置源增加一個擴充套件方法。
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等。預設配置表的名稱為Configuration。
最後
在專案中使用可以執行下面的命令
Install-Package Cxlt.Extensions.Configuration.EF
或
dotnet add package Cxlt.Extensions.Configuration.EF
下篇文章《實現自己的.NET Core配置Provider之Yaml》將講解Yaml配置Provider的細節。
如果這篇文章對你有幫助,請點贊支援一下,也歡迎關注“chengxulvtu"公眾號。