17

ASP.NET Core快速入门(第2章:配置管理)--学习笔记

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzAwNTMxMzg1MA%3D%3D&%3Bmid=2654076985&%3Bidx=4&%3Bsn=318d54d017742c003538227d220ab89e
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

B36ZRbU.png!web

点击 蓝字 关注我们

B36ZRbU.png!web

课程链接:http://video.jessetalk.cn/course/explore

良心课程,大家一起来学习哈!

任务9:配置介绍

  • 命令行配置

  • Json文件配置

  • 从配置文件文本到c#对象实例的映射 - Options 与 Bind

  • 配置文件热更新

  • 框架设计:Configuration

任务10:命令行配置

新建项目CommandLineSample--控制台应用(.NET Core)

管理NuGet程序包--下载microsoft.aspnetcore.all

a6r6B3u.png!web

传入参数

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

UFfABny.png!web

启动项目

J3muUzZ.png!web

默认参数

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();
        }
    }
}

清空应用程序参数

Eb6b2qj.png!web

启动项目

FZBB3aM.png!web

通过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

aEfAVvM.png!web

{
  "ClassNo": "1",
  "ClassDesc": "ASP.NET Core 101",

  "Students": [
    {
      "name": "mingsonzheng",
      "age": "18"
    },
    {
      "name": "jim",
      "age": "28"
    },
    {
      "name": "tom",
      "age": "38"
    }
  ]
}

由于class.json不在bin\Debug目录下,所以默认不会被编译,文件右键属性,修改为始终复制

AJnqyyM.png!web

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文件

NZBV73V.png!web

读取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();
        }
    }
}

启动项目

QjEN3qI.png!web

任务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");
            });
        }
    }
}

启动项目

imU7Nvi.png!web

任务13:在Core Mvc中使用Options

在项目OptionsBindSample新建三个文件夹目录如下

iiaAj2m.png!web

在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");
            //});
        }
    }
}

启动项目

Rryimur.png!web

如果仅仅在视图中使用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

启动项目

jMNvQnj.png!web

修改appsettings的ClassNo为222,保存

"ClassNo": "222",

刷新网页

7zuM3ib.png!web

实现原理

对比控制台程序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;
}

QvMRviU.png!web

bM3UfiA.png!web

yIRR32u.jpg!web

点“在看”给我一朵小黄花

i6z6f2I.png!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK