任務9:配置介紹
-
命令行配置
-
Json文件配置
-
從配置文件文本到c#對象實例的映射 - Options 與 Bind
-
配置文件熱更新
-
框架設計:Configuration
任務10:命令行配置
新建項目CommandLineSample--控制檯應用(.NET Core)
管理NuGet程序包--下載microsoft.aspnetcore.all
傳入參數
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();
}
}
}
項目右鍵--調試--輸入參數:name=mingsonzheng age=18
啓動項目
默認參數
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();
}
}
}
清空應用程序參數
啓動項目
通過PowerShell運行程序,默認參數與傳入參數對比
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
任務11:Json文件配置
新建項目JsonComfigSample--控制檯應用(.NET Core)
管理NuGet程序包--下載microsoft.aspnetcore.all
添加Json文件:項目右鍵--添加新建項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目錄下,所以默認不會被編譯,文件右鍵屬性,修改爲始終複製
using System;
using Microsoft.Extensions.Configuration;
namespace JsonComfigSample
{
class Program
{
static void Main(string[] args)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("class.json");
Console.ReadLine();
}
}
}
啓動項目,可以看到class.json被複制到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");
// 調用Build之前請確保拷貝的class.json文件沒有格式錯誤
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();
}
}
}
啓動項目
任務12:Bind讀取配置到C#實例
新建ASP.NET Core Web 應用程序OptionsBindSample,直接選擇 空,確定
在Startup.cs中通過依賴注入添加configuration
public IConfiguration Configuration { get; set; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
項目右鍵,新建項,添加一個類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; }
}
}
項目右鍵,新建項,添加一個Json文件appsettings.json
爲什麼取名appsettings.json呢?
因爲Program.cs中的CreateDefaultBuilder默認讀取一個名爲appsettings.json的Json文件並把它的內容添加到配置文件
拷貝前面的內容到appsettings.json
{
"ClassNo": "1",
"ClassDesc": "ASP.NET Core 101",
"Students": [
{
"name": "mingsonzheng",
"age": "18"
},
{
"name": "jim",
"age": "28"
},
{
"name": "tom",
"age": "38"
}
]
}
在Startup.cs中通過Bind讀取配置
app.Run(async (context) =>
{
var myClass = new Class();
Configuration.Bind(myClass);// 實現配置文件信息與對象的映射
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; }
// 通過依賴注入添加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");
});
}
}
}
啓動項目
任務13:在Core Mvc中使用Options
在項目OptionsBindSample新建三個文件夾目錄如下
在Controllers文件夾右鍵,添加一個控制器,默認,HomeController
在Home文件夾右鍵,添加一個視圖,默認,Index
在Startup.cs中註釋掉這一段代碼,不然會把整個管道提交,只輸出這一段
//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();
使用默認路由
app.UseMvcWithDefaultRoute();
HomeController中通過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;
// 通過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>
註冊Class,可以通過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; }
// 通過依賴注入添加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)
{
// 註冊Class,可以通過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();
}
// 使用默認路由
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");
//});
}
}
}
啓動項目
如果僅僅在視圖中使用options的話,HomeController的代碼有點多餘,可以直接在視圖中注入
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();
}
}
}
啓動項目得到同樣結果
任務14:配置的熱更新
ASP.NET修改web.config後站點會自動重啓實現熱更新
ASP.NET Core不同,實現如下:
將Index的這一行
@inject IOptions<OptionsBindSample.Class> ClassAccesser
修改爲
@inject IOptionsSnapshot<OptionsBindSample.Class> ClassAccesser
啓動項目
修改appsettings的ClassNo爲222,保存
"ClassNo": "222",
刷新網頁
實現原理
對比控制檯程序JsonComfigSample的Program讀取配置文件
// 第二個參數表示文件不存在時是否拋異常
// 第三個參數表示配置文件更新的時候是否重新加載
var builder = new ConfigurationBuilder()
.AddJsonFile("class.json",false,true);
而在ASP.NET Core程序OptionsBindSample在Program中的CreateDefaultBuilder的源碼實現了
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
WebHost源碼:
https://github.com/aspnet/MetaPackages/blob/master/src/Microsoft.AspNetCore/WebHost.cs
源碼裏面實現熱更新(165行)
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
由於它是WebHostBuilder的一個擴展函數,所以可以覆蓋該方法
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
// 如果業務場景不需要一個線程一直關注配置文件變更,可以關閉熱更新
.ConfigureAppConfiguration(config => { config.AddJsonFile("appsettings.json", false, false); })
.UseStartup<Startup>();
啓動項目,修改配置文件,保存,刷新網頁,內容不會熱更新
任務15:配置框架設計淺析
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;
}