《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