【ASP.NET Core學習】基礎知識,配置文件,日誌,依賴註入 ...
新建項目時,程式入口調用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; }View Code
從上面代碼看見這個方法幫我們處理的東西
- 設置根目錄為當前目錄
- 配置應用程式配置
- 配置日誌配置
- 配置依賴註入
配置文件
配置文件內容如下{"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