前言
最近有點忙,學習有點懈怠(慚愧),抽時間學習把這篇部落格寫完,希望理解。相信自己能堅持下去,把這個系列寫完。好啦,開搞。說道配置檔案,基本大多數軟體為了擴充套件性、靈活性都會涉及到配置檔案,比如之前常見的app.config和web.config。然後再說.NET Core,很多都發生了變化。總體的來說技術在進步,新的方式更加輕量級,具有更好的擴充套件性,資料來源更加多樣性。
ASP.NET Core 應用可用的配置提供程式
提供程式 | 一下物件提供配置 |
---|---|
Azure Key Vault 配置提供程式 | Azure Key Vault |
Azure 應用配置提供程式 | Azure 應用程式配置 |
命令列配置提供程式 | 命令列引數 |
自定義配置提供程式 | 自定義源 |
環境變數配置提供程式 | 環境變數 |
檔案配置提供程式 | INI、JSON 和 XML 檔案 |
Key-per-file 配置提供程式 | 目錄檔案 |
記憶體配置提供程式 | 記憶體中集合 |
使用者機密 | 使用者配置檔案目錄中的檔案 |
配置提供程式的典型順序為:
1.appsettings.json
2.appsettings.Environment.json
3.使用者機密
4.使用環境變數配置提供程式通過環境變數提供。
5.使用命令列配置提供程式通過命令列引數提供。
注意: 通常的做法是將命令列配置提供程式新增到一系列提供程式的末尾,使命令列引數能夠替代由其他提供程式設定的配置。
配置模型三要素
.NET Core的配置系統由三個核心物件構成,分別是IConfiguration、IConfigurationBuilder、IConfigurationSource。
- IConfiguration:讀取出來的配置資訊最終會轉換成一個IConfiguration物件供應用程式使用。
- IConfigurationBuilder:IConfigurationBuilder是IConfiguration物件的構建者。
- IConfigurationSource:則代表配置資料最原始的來源。
檔案配置
讀取INI檔案配置
首先建立一個ASP .NET Core Web API專案,在主目錄下新增MyIniConfig.ini檔案。
ID=1
Title="INIConfig title"
Name="INIConfig name"
[Logging:LogLevel]
Default=Information
在Program類中讀取配置檔案
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.Sources.Clear();
var env = hostingContext.HostingEnvironment;
config.AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true); config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
新建一個名為SettingsController的控制器,讀取配置檔案。
[Route("api/[controller]/[action]")]
[ApiController]
public class SettingsController : ControllerBase
{
private readonly IConfiguration Configuration;
public SettingsController(IConfiguration configuration)
{
Configuration = configuration;
}
public ContentResult INISetting()
{
int id = Configuration.GetValue<int>("ID");
var title = Configuration["Title"];
var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
return Content($"ID:{id}\n" +$"Title:{title}\n"+
$"Default Log Level: {defaultLogLevel}");
}
}
利用PostMan可以看到已經讀取到剛剛設定的INI檔案。
讀取Json配置檔案。
新建ASP.NET Core Web API專案,在主目錄下新增MyJsonConfig.json檔案。
{
"ID": "1",
"Title": "My JsonConfig",
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
在Program類中讀取配置檔案
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.Sources.Clear();
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("MyJsonConfig.json", optional: true, reloadOnChange: true);
config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
新建一個名為SettingsController的控制器,讀取配置檔案。
[Route("api/[controller]/[action]")]
[ApiController]
public class SettingsController : ControllerBase
{
private readonly IConfiguration Configuration;
public SettingsController(IConfiguration configuration)
{
Configuration = configuration;
}
public ContentResult JsonSetting()
{
int id = Configuration.GetValue<int>("ID");
var title = Configuration["Title"];
var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
return Content($"ID:{id}\n" + $"Title:{title}\n" +
$"Default Log Level: {defaultLogLevel}");
}
}
利用PostMan可以看到已經讀取到剛剛設定的Json檔案。
讀取XML檔案
新建ASP.NET Core Web API專案,在主目錄下新增MyXMLConfig.xml檔案。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<ID>1</ID>
<Title>MyXMLConfig Title</Title>
<Name>MyXMLConfig Name</Name>
<Logging>
<LogLevel>
<Default>Information</Default>
</LogLevel>
</Logging>
</configuration>
在Program類中讀取配置檔案
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.Sources.Clear();
var env = hostingContext.HostingEnvironment;
config.AddXmlFile("MyXMLConfig.xml", optional: true, reloadOnChange: true);
config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
新建一個名為SettingsController的控制器,讀取配置檔案。
[Route("api/[controller]/[action]")]
[ApiController]
public class SettingsController : ControllerBase
{
private readonly IConfiguration Configuration;
public SettingsController(IConfiguration configuration)
{
Configuration = configuration;
}
public ContentResult XmlSetting()
{
int id = Configuration.GetValue<int>("ID");
var title = Configuration["Title"];
var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
return Content($"ID:{id}\n" + $"Title:{title}\n" +
$"Default Log Level: {defaultLogLevel}");
}
}
利用PostMan可以看到已經讀取到XML檔案的配置。
讀取配置項的方法
說幾個在讀取配置項中比較常用的方法,大家可以根據上面例子,自己試一下,這裡就不詳細講解了。
GetValue
ConfigurationBinder.GetValueint id = Configuration.GetValue
就是利用這個方法獲取指定型別。
GetSection
IConfiguration.GetSection 會返回具有指定子節鍵的配置子節。
GetChildren
IConfiguration.GetChildren 方法獲取直接後代配置子節。
Exists
ConfigurationExtensions.Exists(IConfigurationSection)確定該部分是否具有 Value 或子級。
將配置繫結到物件
新建ASP.NET Core Web API專案,在主目錄下新增MyArray.json檔案。
{
"array": {
"entries": {
"0": "value0",
"1": "value1",
"2": "value2",
"3": "value3"
}
}
}
建立一個model。
public class Model
{
public string[] Entries { get; set; }
}
在Program類中讀取配置檔案
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.Sources.Clear();
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("MyArray.json",optional: true,reloadOnChange: true);
config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
新建一個名為SettingsController的控制器,讀取配置檔案。
[Route("api/[controller]/[action]")]
[ApiController]
public class SettingsController : ControllerBase
{
private readonly IConfiguration Configuration;
public SettingsController(IConfiguration configuration)
{
Configuration = configuration;
}
public ContentResult ToModel()
{
array = Configuration.GetSection("array").Get<Model>();
string modelStr = null;
for (int j = 0; j < array.Entries.Length; j++)
{
modelStr += $"Index: {j} Value: {array.Entries[j]} \n";
}
return Content(modelStr);
}
}
利用PostMan可以看到已經讀取到繫結到Model的配置。
自定義配置
如果上面的方式還不能滿足專案要求的話,還可以從資料庫中讀取配置資訊。接下來我們通過實體框架(EF)讀取資料庫中配置資訊(埋個伏筆,後續做個相關教程)。便於操作,這次使用記憶體資料庫做配置源。
首先做一個建立一個實體。
public class EFModel
{
public int ID { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
新增 EFConfigContext 以儲存和訪問配置的值。
public class EFConfigContext:DbContext
{
public EFConfigContext(DbContextOptions options) : base(options)
{
}
public DbSet<EFModel> Values { get; set; }
}
建立用於實現 IConfigurationSource 的類。
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);
}
}
通過從 ConfigurationProvider 繼承來建立自定義配置提供程式。 當資料庫為空時,配置提供程式將對其進行初始化。
public class EFConfigurationProvider:ConfigurationProvider
{
Action<DbContextOptionsBuilder> OptionsAction { get; }
public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
{
OptionsAction = optionsAction;
}
public override void Load()
{
var builder = new DbContextOptionsBuilder<EFConfigContext>();
OptionsAction(builder);
using (var dbContext =new EFConfigContext(builder.Options))
{
dbContext.Database.EnsureCreated();
Data =!dbContext.Values.Any()?CreateAndSaveValues(dbContext) : dbContext.Values.ToDictionary(c => c.Name, c => c.Value);
}
}
private static IDictionary<string, string> CreateAndSaveValues(EFConfigContext dbContext)
{
var configValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{"name1","value1" },
{"name2","value2" },
{"name3","value3" }
};
dbContext.Values.AddRange(configValues.Select(v => new EFModel
{
Name = v.Key,
Value = v.Value
}).ToArray());
dbContext.SaveChanges();
return configValues;
}
}
使用 AddEFConfiguration 擴充套件方法將配置源新增到 ConfigurationBuilder。
public static class EFExtensions
{
public static IConfigurationBuilder AddEFConfiguration(this IConfigurationBuilder builder,Action<DbContextOptionsBuilder> optionsAction)
{
return builder.Add(new EFConfigurationSource(optionsAction));
}
}
在 Program.cs 中使用自定義的 EFConfigurationProvider:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.Sources.Clear();
var env = hostingContext.HostingEnvironment;
config.AddEFConfiguration(
options => options.UseInMemoryDatabase("InMemoryDb"));
config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
在Startup中通過依賴注入新增據庫上下文服務,向控制器提供服務。
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<EFConfigContext>(opt => opt.UseInMemoryDatabase("InMemoryDb"));
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
在控制器中注入服務,讀取記憶體資料庫中的資料。
[Route("api/[controller]/[action]")]
[ApiController]
public class SettingsController : ControllerBase
{
private readonly EFConfigContext _efDbContext;
public SettingsController( EFConfigContext efDbContext)
{
_efDbContext = efDbContext;
}
public ActionResult<IEnumerable<EFModel>> EFSetting()
{
List<EFModel> list = _efDbContext.Values.ToList();
return list;
}
}
利用PostMan可以看到已經讀取到我們自定義的配置源。
加一張整體的專案結構,方便大家理解。
最近疫情有些反覆,出門做好個人防護,玩耍時別忘記學習。最後祝大家週末愉快!