ASP.NET Core快速入門(mén)(第2章:配置管理)--學(xué)習(xí)筆記
課程鏈接:http://video.jessetalk.cn/course/explore
良心課程,大家一起來(lái)學(xué)習(xí)哈!
任務(wù)9:配置介紹
- 命令行配置
- Json文件配置
- 從配置文件文本到c#對(duì)象實(shí)例的映射 - Options 與 Bind
- 配置文件熱更新
- 框架設(shè)計(jì):Configuration
任務(wù)10:命令行配置
新建項(xiàng)目CommandLineSample--控制臺(tái)應(yīng)用(.NET Core)
管理NuGet程序包--下載microsoft.aspnetcore.all

傳入?yún)?shù)
using System;
using Microsoft.Extensions.Configuration;
namespace CommandLineSample
{
class Program
{
static void Main(string[] args)
{
var builder = new ConfigurationBuilder()
.AddCommandLine(args);
var configuration = builder.Build();
Console.WriteLine($"name: {configuration ["name"]}");
Console.WriteLine($"age: {configuration["age"]}");
Console.ReadLine();
}
}
}
項(xiàng)目右鍵--調(diào)試--輸入?yún)?shù):name=mingsonzheng age=18

啟動(dòng)項(xiàng)目

默認(rèn)參數(shù)
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
namespace CommandLineSample
{
class Program
{
static void Main(string[] args)
{
var settings = new Dictionary<string, string>
{
{"name", "mingsonzheng" },
{"age", "18" }
};
var builder = new ConfigurationBuilder()
.AddInMemoryCollection(settings)
.AddCommandLine(args);
var configuration = builder.Build();
Console.WriteLine($"name: {configuration ["name"]}");
Console.WriteLine($"age: {configuration["age"]}");
Console.ReadLine();
}
}
}
清空應(yīng)用程序參數(shù)

啟動(dòng)項(xiàng)目

通過(guò)PowerShell運(yùn)行程序,默認(rèn)參數(shù)與傳入?yún)?shù)對(duì)比
PS D:\jessetalk\CommandLineSample\CommandLineSample\bin\Debug\netcoreapp2.1> dotnet CommandLineSample.dll
name: mingsonzheng
age: 18
PS D:\jessetalk\CommandLineSample\CommandLineSample\bin\Debug\netcoreapp2.1> dotnet CommandLineSample.dll name=jim age=22
name: jim
age: 22
任務(wù)11:Json文件配置
新建項(xiàng)目JsonComfigSample--控制臺(tái)應(yīng)用(.NET Core)
管理NuGet程序包--下載microsoft.aspnetcore.all
添加Json文件:項(xiàng)目右鍵--添加新建項(xiàng)class.json

{
"ClassNo": "1",
"ClassDesc": "ASP.NET Core 101",
"Students": [
{
"name": "mingsonzheng",
"age": "18"
},
{
"name": "jim",
"age": "28"
},
{
"name": "tom",
"age": "38"
}
]
}
由于class.json不在bin\Debug目錄下,所以默認(rèn)不會(huì)被編譯,文件右鍵屬性,修改為始終復(fù)制

using System;
using Microsoft.Extensions.Configuration;
namespace JsonComfigSample
{
class Program
{
static void Main(string[] args)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("class.json");
Console.ReadLine();
}
}
}
啟動(dòng)項(xiàng)目,可以看到class.json被復(fù)制到bin\Debug目錄,這樣dll就可以讀取到class.json文件

讀取json文件
using System;
using Microsoft.Extensions.Configuration;
namespace JsonComfigSample
{
class Program
{
static void Main(string[] args)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("class.json");
// 調(diào)用Build之前請(qǐng)確保拷貝的class.json文件沒(méi)有格式錯(cuò)誤
var configuration = builder.Build();
Console.WriteLine($"ClassNo: { configuration["ClassNo"]}");
Console.WriteLine($"ClassDesc: { configuration["ClassDesc"]}");
Console.WriteLine("Students");
Console.Write(configuration["Students:0:name"]);
Console.WriteLine(configuration["Students:0:age"]);
Console.Write(configuration["Students:1:name"]);
Console.WriteLine(configuration["Students:1:age"]);
Console.Write(configuration["Students:2:name"]);
Console.WriteLine(configuration["Students:2:age"]);
Console.ReadLine();
}
}
}
啟動(dòng)項(xiàng)目

任務(wù)12:Bind讀取配置到C#實(shí)例
新建ASP.NET Core Web 應(yīng)用程序OptionsBindSample,直接選擇 空,確定
在Startup.cs中通過(guò)依賴注入添加configuration
public IConfiguration Configuration { get; set; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
項(xiàng)目右鍵,新建項(xiàng),添加一個(gè)類Class.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace OptionsBindSample
{
public class Class
{
public int ClassNo { get; set; }
public string ClassDesc { get; set; }
public List<Student> Students { get; set; }
}
public class Student
{
public string Name { get; set; }
public string Age { get; set; }
}
}
項(xiàng)目右鍵,新建項(xiàng),添加一個(gè)Json文件appsettings.json
為什么取名appsettings.json呢?
因?yàn)镻rogram.cs中的CreateDefaultBuilder默認(rèn)讀取一個(gè)名為appsettings.json的Json文件并把它的內(nèi)容添加到配置文件
拷貝前面的內(nèi)容到appsettings.json
{
"ClassNo": "1",
"ClassDesc": "ASP.NET Core 101",
"Students": [
{
"name": "mingsonzheng",
"age": "18"
},
{
"name": "jim",
"age": "28"
},
{
"name": "tom",
"age": "38"
}
]
}
在Startup.cs中通過(guò)Bind讀取配置
app.Run(async (context) =>
{
var myClass = new Class();
Configuration.Bind(myClass);// 實(shí)現(xiàn)配置文件信息與對(duì)象的映射
await context.Response.WriteAsync($"ClassNo: { myClass.ClassNo}");
await context.Response.WriteAsync($"ClassDesc: { myClass.ClassDesc}");
await context.Response.WriteAsync($" {myClass.Students.Count } Students");
});
完整Startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace OptionsBindSample
{
public class Startup
{
public IConfiguration Configuration { get; set; }
// 通過(guò)依賴注入添加configuration
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Run(async (context) =>
{
var myClass = new Class();
Configuration.Bind(myClass);// Bind讀取配置
await context.Response.WriteAsync($"ClassNo: { myClass.ClassNo}");
await context.Response.WriteAsync($"ClassDesc: { myClass.ClassDesc}");
await context.Response.WriteAsync($" {myClass.Students.Count } Students");
});
}
}
}
啟動(dòng)項(xiàng)目

任務(wù)13:在Core Mvc中使用Options
在項(xiàng)目OptionsBindSample新建三個(gè)文件夾目錄如下

在Controllers文件夾右鍵,添加一個(gè)控制器,默認(rèn),HomeController
在Home文件夾右鍵,添加一個(gè)視圖,默認(rèn),Index
在Startup.cs中注釋掉這一段代碼,不然會(huì)把整個(gè)管道提交,只輸出這一段
//app.Run(async (context) =>
//{
// var myClass = new Class();
// Configuration.Bind(myClass);// Bind讀取配置
// await context.Response.WriteAsync($"ClassNo: { myClass.ClassNo}");
// await context.Response.WriteAsync($"ClassDesc: { myClass.ClassDesc}");
// await context.Response.WriteAsync($" {myClass.Students.Count } Students");
//});
依賴注入配置添加MVC
services.AddMvc();
使用默認(rèn)路由
app.UseMvcWithDefaultRoute();
HomeController中通過(guò)IOptions方式依賴注入
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
namespace OptionsBindSample.Controllers
{
public class HomeController : Controller
{
private readonly Class _myClass;
// 通過(guò)IOptions方式依賴注入
public HomeController(IOptions<Class> classAccesser)
{
_myClass = classAccesser.Value;
}
public IActionResult Index()
{
return View(_myClass);
}
}
}
在Index中定義模型,輸出
@model OptionsBindSample.Class
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<h4>Class No: @Model.ClassNo</h4>
<h4>Class Desc: @Model.ClassDesc</h4>
<h3>
Students:
</h3>
<div>
@foreach (var student in Model.Students)
{
<span>Name: @student.Name</span>
<span>Age: @student.Age</span>
}
</div>
注冊(cè)Class,可以通過(guò)Configuration讀取到option
services.Configure<Class>(Configuration);
Startup.cs完整代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace OptionsBindSample
{
public class Startup
{
public IConfiguration Configuration { get; set; }
// 通過(guò)依賴注入添加configuration
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
// 注冊(cè)Class,可以通過(guò)Configuration讀取到option
services.Configure<Class>(Configuration);
// 依賴注入配置添加MVC
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// 使用默認(rèn)路由
app.UseMvcWithDefaultRoute();
//app.Run(async (context) =>
//{
// var myClass = new Class();
// Configuration.Bind(myClass);// Bind讀取配置
// await context.Response.WriteAsync($"ClassNo: { myClass.ClassNo}");
// await context.Response.WriteAsync($"ClassDesc: { myClass.ClassDesc}");
// await context.Response.WriteAsync($" {myClass.Students.Count } Students");
//});
}
}
}
啟動(dòng)項(xiàng)目

如果僅僅在視圖中使用options的話,HomeController的代碼有點(diǎn)多余,可以直接在視圖中注入
Index
@using Microsoft.Extensions.Options;
@inject IOptions<OptionsBindSample.Class> ClassAccesser
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<h4>Class No: @ClassAccesser.Value.ClassNo</h4>
<h4>Class Desc: @ClassAccesser.Value.ClassDesc</h4>
<h3>
Students:
</h3>
<div>
@foreach (var student in ClassAccesser.Value.Students)
{
<span>Name: @student.Name</span>
<span>Age: @student.Age</span>
}
</div>
HomeController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
namespace OptionsBindSample.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
啟動(dòng)項(xiàng)目得到同樣結(jié)果
任務(wù)14:配置的熱更新
ASP.NET修改web.config后站點(diǎn)會(huì)自動(dòng)重啟實(shí)現(xiàn)熱更新
ASP.NET Core不同,實(shí)現(xiàn)如下:
將Index的這一行
@inject IOptions<OptionsBindSample.Class> ClassAccesser
修改為
@inject IOptionsSnapshot<OptionsBindSample.Class> ClassAccesser
啟動(dòng)項(xiàng)目

修改appsettings的ClassNo為222,保存
"ClassNo": "222",
刷新網(wǎng)頁(yè)

實(shí)現(xiàn)原理
對(duì)比控制臺(tái)程序JsonComfigSample的Program讀取配置文件
// 第二個(gè)參數(shù)表示文件不存在時(shí)是否拋異常
// 第三個(gè)參數(shù)表示配置文件更新的時(shí)候是否重新加載
var builder = new ConfigurationBuilder()
.AddJsonFile("class.json",false,true);
而在ASP.NET Core程序OptionsBindSample在Program中的CreateDefaultBuilder的源碼實(shí)現(xiàn)了
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
WebHost源碼:
https://github.com/aspnet/MetaPackages/blob/master/src/Microsoft.AspNetCore/WebHost.cs
源碼里面實(shí)現(xiàn)熱更新(165行)
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
由于它是WebHostBuilder的一個(gè)擴(kuò)展函數(shù),所以可以覆蓋該方法
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
// 如果業(yè)務(wù)場(chǎng)景不需要一個(gè)線程一直關(guān)注配置文件變更,可以關(guān)閉熱更新
.ConfigureAppConfiguration(config => { config.AddJsonFile("appsettings.json", false, false); })
.UseStartup<Startup>();
啟動(dòng)項(xiàng)目,修改配置文件,保存,刷新網(wǎng)頁(yè),內(nèi)容不會(huì)熱更新
任務(wù)15:配置框架設(shè)計(jì)淺析
var builder = new ConfigurationBuilder();// 初始化Builder
builder.Add(source);// 將source添加到Builder
=>
JsonConfigurationSource source = new
JsonConfigurationSource()
{
Path = "settings.json";
};
var configurationRoot = builder.Build();// Build
=>
foreach(var source in sources)
{
var provider = source.Build();
providers.add(provider);
}
return new ConfigurationRoot(providers);
configurationRoot["Key"]// Use
=>
foreach(var provider in providers.Reverse())
{
string value;
provider.TryGet(Key, out Value)
return value;
}



本作品采用知識(shí)共享署名-非商業(yè)性使用-相同方式共享 4.0 國(guó)際許可協(xié)議進(jìn)行許可。
歡迎轉(zhuǎn)載、使用、重新發(fā)布,但務(wù)必保留文章署名 鄭子銘 (包含鏈接: http://www.rzrgm.cn/MingsonZheng/ ),不得用于商業(yè)目的,基于本文修改后的作品務(wù)必以相同的許可發(fā)布。
如有任何疑問(wèn),請(qǐng)與我聯(lián)系 (MingsonZheng@outlook.com) 。


浙公網(wǎng)安備 33010602011771號(hào)