新建项目时,程序入口调用CreateDefaultBuilder(args),下面是源代码
public static IHostBuilder CreateDefaultBuilder(string[] args) { var builder = new HostBuilder(); builder.UseContentRoot(Directory.GetCurrentDirectory()); builder.ConfigureHostConfiguration(config => { config.AddEnvironmentVariables(prefix: "DOTNET_"); if (args != null) { config.AddCommandLine(args); } }); builder.ConfigureAppConfiguration((hostingContext, config) => { var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName)) { var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName)); if (appAssembly != null) { config.AddUserSecrets(appAssembly, optional: true); } } config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) .ConfigureLogging((hostingContext, logging) => { var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); // IMPORTANT: This needs to be added *before* configuration is loaded, this lets // the defaults be overridden by the configuration. if (isWindows) { // Default the EventLogLoggerProvider to warning or above logging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning); } logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); logging.AddConsole(); logging.AddDebug(); logging.AddEventSourceLogger(); if (isWindows) { // Add the EventLogLoggerProvider on windows machines logging.AddEventLog(); } }) .UseDefaultServiceProvider((context, options) => { var isDevelopment = context.HostingEnvironment.IsDevelopment(); options.ValidateScopes = isDevelopment; options.ValidateOnBuild = isDevelopment; }); return builder; }
从上面代码看见这个方法帮我们处理的东西
- 设置根目录为当前目录
- 配置应用程序配置
- 配置日志配置
- 配置依赖注入
配置文件
配置文件内容如下
{"Setting": { "Name": "Wilson", "Date": "2019-10-28" } }
一、注入IConfiguration
public IndexModel(IConfiguration config) { var name = config.GetSection("Setting").GetValue<string>("Name"); var date = config.GetSection("Setting").GetValue<DateTime>("Date");}
二、通过IOptions注入
1. 在ConfigureServices添加Options支持和配置文件节点
public void ConfigureServices(IServiceCollection services) { services.AddOptions(); services.Configure<Setting>(Configuration.GetSection("Setting")); }
2. 构造函数里面注入IOptions
public IndexModel(IOptions<Setting> option) { var setting = option.Value; var name = setting.Name; var date = setting.Date; }
三、绑定到类
public IndexModel(IConfiguration config) { var setting = new Setting(); config.GetSection("Setting").Bind(setting); }
或者
public IndexModel(IConfiguration config) { var setting = config.GetSection("Setting").Get<Setting>(); }
四、页面读取配置文件
@using Microsoft.Extensions.Configuration @inject IConfiguration Configuration <div class="text-center"> <h3 class="color-red">@Configuration["Setting:Name"]</h3> </div>
我个人推荐使用第二种方式去读取配置文件,因为它隐藏了如何读取配置文件,只需要获取我们关心的信息即可,第一,第三种都在不同地方使用硬编码的方式去读取(当然可以设置为常量),而且还有知道节点信息
开发过程通常不同环境是读取不同配置,ASPNET Core提供了一个很方便的方法去实现
截取源代码部分代码
var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
它会除了加载appsettings.json外,还好加载当前环境的json配置文件
我们只要设置当前环境环境变量(项目设置或者当前电脑环境变量添加ASPNETCORE_ENVIRONMENT)就能加载不同配置文件
日志
截取源代码部分代码
var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); // IMPORTANT: This needs to be added *before* configuration is loaded, this lets // the defaults be overridden by the configuration. if (isWindows) { // Default the EventLogLoggerProvider to warning or above logging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning); } logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); logging.AddConsole(); logging.AddDebug(); logging.AddEventSourceLogger(); if (isWindows) { // Add the EventLogLoggerProvider on windows machines logging.AddEventLog(); }
除了配置基本信息,Windows操作系统Waring以上的日志还会写入到EventLog
现在我们写几个日志试试,因为配置了,所以我们直接注入logger写日志
public IndexModel(Logger<IndexModel> logger) { logger.LogDebug("This is Debug Message"); logger.LogInformation("This is Information Message"); logger.LogWarning("This is Warning Message"); logger.LogError("This is Error Message"); }
看到控制台输出
接着我们看看Evenlog有没有写入数
我们看到警告基本以上的日志都写入了
实际应用我们通常需要将日志写入文本文件,但ASPNET Core内置日志记录提供程序并没有提供文本文件的程序,但是我们可以使用第三方日志组件(例如log4net)
1. Nuget添加log4net(Microsoft.Extensions.Logging.Log4Net.AspNetCore)
2. 调用日志记录框架提供的 ILoggerFactory 扩展方法。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddLog4Net(); ..... }
访问一下,看看写入日志
可以看到,除了中间那段是我们写入的,其他都是系统的日志
在源代码里面可以看到,系统是添加Logging节点的配置信息,里面可以指定日志类别
"Logging": { "LogLevel": { "Default": "Debug", "System": "Warning", "Microsoft": "Warning" } }
指定System和Microsoft类别为Warning,只有高于这个级别才会输出到日志
可以设置莫一类别的日志级别
"Logging": { "LogLevel": { "Default": "Debug", "System": "Warning", "Microsoft": "Information", "Microsoft.AspNetCore.Mvc":"Warning" } }
只能设置大的级别再设置小级别才有效,即若只设置Microsoft.AspNetCore.Mvc,不设置Microsoft就不起效果
依赖注入
ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式,这是一种在类及其依赖关系之间实现控制反转 (IoC) 的技术。
在CreateDefaultBuilder最后是一个扩展方法,使用默认的DefaultServiceProviderFactory
ASP.NET Core 提供三种注册方法
方法 | 描述 | 适合场景 |
---|---|---|
AddTransient |
每次从服务容器进行请求时都是新建 | 轻量级、 无状态的服务 |
AddScoped |
每次请求/连接是同一个对象 | Http请求需要保持同一个对象 |
AddSingleton |
单例 | 单例对象 |
一、添加服务
public void ConfigureServices(IServiceCollection services) { ... services.AddSingleton<IServiceSingleton, ServiceSingleton>(); services.AddScoped<IServiceScoped, ServiceScoped>(); services.AddTransient<IServicesTransient, ServicesTransient>(); services.AddTransient<IMyService, MyService>(); }
二、 获取服务方式
1. 构造函数获取
public IndexModel(IServicesTransient servicesTransient) { }
2. 通过IHttpContextAccessor获取
2.1 注入IHttpContextAccessor
public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); }
2.2 通过RequestServices获取
var service = accessor.HttpContext.RequestServices.GetService<IMyService>(); service.Run();
三、使用第三方容器
内置的容器实现最基本的注入方式,已经能满足大部分项目需求。但是有时候可能需要特殊的需求,例如属性注入、基于名称的注入、自定义生存期管理等功能时,内置的容器不支持这些功能。下面介绍如何替换内置容器,以Autofac为例
1. nuget 添加Autofac.Extensions.DependencyInjection
2. Program替换容器
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseServiceProviderFactory(new AutofacServiceProviderFactory())
3. Startup类添加方法ConfigureContainer
public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>(); builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()) .Where(m => m.Name.Contains("Service")) .AsImplementedInterfaces() .InstancePerLifetimeScope(); }
这是ASPNET Core 3.0+版本替换Autofac方法,3.0不支持返回IServiceProvider
Autofac.Extensions.DependencyInjection
原文地址:https://www.cnblogs.com/WilsonPan/p/11751028.html