序言 使用.NET Core,團隊可以更容易專註的在.net core上工作。比如核心類庫(如System.Collections)的更改仍然需要與.NET Framework相同的活力,但是ASP.NET Core或Entity Framework Core可以更輕鬆地進行實質性更改,而不受向後兼 ...
序言
使用.NET Core,團隊可以更容易專註的在.net core上工作。比如核心類庫(如System.Collections)的更改仍然需要與.NET Framework相同的活力,但是ASP.NET Core或Entity Framework Core可以更輕鬆地進行實質性更改,而不受向後相容性的限制。.NET Core借鑒了.NET Framework的最佳實踐,並將軟體工程的最新進展結合在一起。
寒暄、扯淡已經完畢,,,下麵是我最近時間對.Net Core整理的相關知識,覺得這些在項目中是最基礎且最會應用到的,,,,不喜歡扯理論,直接擼碼:
1、淺談Startup類
2、自定義路由
3、跨域設置
4、自定義讀取配置文件信息
5、程式集批量依賴註入
6、使用NLog寫入文件日誌
7、使用NLog寫入資料庫日誌
8、Nlog標簽解讀
一、淺談Startup類
在ASP.NET Core應用程式中,使用一個按約定Startup
命名的類Startup
,在Program.cs中使用WebHostBuilderExtensions UseStartup <TStartup>方法指定類,但通常使用系統預設的startup,可以通過startup的構造函數進行依賴註入,startup類中必須包含Configure方法同時可以根據實際情況添加ConfigureServices方法,這兩個方法均在應用程式運行時被調用。Startup 類的 執行順序:構造 -> configureServices ->configure
ConfigureServices方法:主要用於服務配置,比如依賴註入(DI)的配置,使用時該方法必須在Configure方法之前
Configure方法:用於應用程式響應HTTP請求,通過向IApplicationBuilder實例添加中間件組件來配置請求管道
二、自定義路由
在Startup類的Configure方法配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } #region 自定義路由配置 app.UseMvc(routes => { // 自定義路由 routes.MapRoute( name: "default1", template: "api/{controller}/{action}/{id?}", defaults: new { controller = "Values", action = "Index" }); // 預設路由 routes.MapRoute( name: "default", template: "{controller}/{action}/{id?}", defaults: new { controller = "Values", action = "Index" }); }); #endregion }View Code
三、跨域設置
在Startup類的ConfigureServices方法配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public void ConfigureServices(IServiceCollection services) { #region 跨域設置 services.AddCors(options => { options.AddPolicy("AppDomain", builder => { builder.AllowAnyOrigin() // Allow access to any source from the host .AllowAnyMethod() // Ensures that the policy allows any method .AllowAnyHeader() // Ensures that the policy allows any header .AllowCredentials(); // Specify the processing of cookie }); }); #endregion services.AddMvc(); }View Code
其中“AppDomain”這個名字是自定義的,大家可以根據自己的喜好定義不同的名字,配置完成之後,在控制器上面添加[EnableCors("AppDomain")]特性即可,如果要實現全局的跨域設置,可以在Configure方法裡面配置app.UseCors("AppDomain"),即能實現全局的跨域設置
四、自定義讀取配置文件信息
這裡是寫的一個公共方法去讀取配置文件appsettings.json
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Json; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using System.IO; public class JsonConfigurationHelper { public static T GetAppSettings<T>(string key,string path= "appsettings.json") where T : class, new() { var currentClassDir = Directory.GetCurrentDirectory(); IConfiguration config = new ConfigurationBuilder() .SetBasePath(currentClassDir) .Add(new JsonConfigurationSource { Path = path, Optional = false, ReloadOnChange = true }) .Build(); var appconfig = new ServiceCollection() .AddOptions() .Configure<T>(config.GetSection(key)) .BuildServiceProvider() .GetService<IOptions<T>>() .Value; return appconfig; } }View Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/// <summary> /// 讀取配置文件 /// </summary> /// <returns></returns> [HttpGet] public dynamic JsonConfig() { var jsonStr = JsonConfigurationHelper.GetAppSettings<ConfigDTO>("config"); return Ok(jsonStr); } /// <summary> /// 實體類 /// </summary> public class ConfigDTO { public dynamic name { get; set; } }View Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{ "config": { "name": "Core.Api" } }View Code
截圖看效果
五、程式集批量依賴註入
我們都知道依賴註入主要是為了方便解耦,解除應用程式之間的依賴關係,在我看來DI、IOC這兩者差不多是一樣的,DI是從應用程式的角度而IOC是從容器的角度,它們主要是對同一件事情的不同角度的描述。然而,,,,,,當我們項目業務比較多的時候,如果要實現多個業務的註入,通常方法是手動一個個的添加註入,這樣可能有點太繁瑣,所以就想到了利用反射實現批量註入,,,,,,
幫助類
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class RuntimeHelper { /// <summary> /// 獲取項目程式集,排除所有的系統程式集(Microsoft.***、System.***等)、Nuget下載包 /// </summary> /// <returns></returns> public static IList<Assembly> GetAllAssemblies() { var list = new List<Assembly>(); var deps = DependencyContext.Default; var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");//排除所有的系統程式集、Nuget下載包 foreach (var lib in libs) { try { var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name)); list.Add(assembly); } catch (Exception) { // ignored } } return list; } public static Assembly GetAssembly(string assemblyName) { return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName)); } public static IList<Type> GetAllTypes() { var list = new List<Type>(); foreach (var assembly in GetAllAssemblies()) { var typeInfos = assembly.DefinedTypes; foreach (var typeInfo in typeInfos) { list.Add(typeInfo.AsType()); } } return list; } public static IList<Type> GetTypesByAssembly(string assemblyName) { var list = new List<Type>(); var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName)); var typeInfos = assembly.DefinedTypes; foreach (var typeInfo in typeInfos) { list.Add(typeInfo.AsType()); } return list; } public static Type GetImplementType(string typeName, Type baseInterfaceType) { return GetAllTypes().FirstOrDefault(t => { if (t.Name == typeName && t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name)) { var typeInfo = t.GetTypeInfo(); return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType; } return false; }); } }View Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public static class ServiceExtension { /// <summary> /// 用DI批量註入介面程式集中對應的實現類。 /// </summary> /// <param name="service"></param> /// <param name="interfaceAssemblyName"></param> /// <returns></returns> public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName) { if (service == null) throw new ArgumentNullException(nameof(service)); if (string.IsNullOrEmpty(interfaceAssemblyName)) throw new ArgumentNullException(nameof(interfaceAssemblyName)); var assembly = RuntimeHelper.GetAssembly(interfaceAssemblyName); if (assembly == null) { throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found"); } //過濾掉非介面及泛型介面 var types = assembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType); foreach (var type in types) { var implementTypeName = type.Name.Substring(1); var implementType = RuntimeHelper.GetImplementType(implementTypeName, type); if (implementType != null) service.AddSingleton(type, implementType); } return service; } /// <summary> /// 用DI批量註入介面程式集中對應的實現類。 /// </summary> /// <param name="service"></param> /// <param name="interfaceAssemblyName">介面程式集的名稱(不包含文件擴展名)</param> /// <param name="implementAssemblyName">實現程式集的名稱(不包含文件擴展名)</param> /// <returns></returns> public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName, string implementAssemblyName) { if (service == null) throw new ArgumentNullException(nameof(service)); if (string.IsNullOrEmpty(interfaceAssemblyName)) throw new ArgumentNullException(nameof(interfaceAssemblyName)); if (string.IsNullOrEmpty(implementAssemblyName)) throw new ArgumentNullException(nameof(implementAssemblyName)); var interfaceAssembly = RuntimeHelper.GetAssembly(interfaceAssemblyName); if (interfaceAssembly == null) { throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found"); } var implementAssembly = RuntimeHelper.GetAssembly(implementAssemblyName); if (implementAssembly == null) { throw new DllNotFoundException($"the dll \"{implementAssemblyName}\" not be found"); } //過濾掉非介面及泛型介面 var types = interfaceAssembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType); foreach (var type in types) { //過濾掉抽象類、泛型類以及非class var implementType = implementAssembly.DefinedTypes .FirstOrDefault(t => t.IsClass && !t.IsAbstract && !t.IsGenericType && t.GetInterfaces().Any(b => b.Name == type.Name)); if (implementType != null) { service.AddSingleton(type, implementType.AsType()); } } return service; } }View Code
在Startupl類的ConfigureServices方法中添加
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { #region 程式集批量依賴註入 services.RegisterAssembly("Core.BLL"); #endregion services.AddMvc(); }View Code
調用(Ps:Core.BLL這個類庫裡面分別有一個介面IAccountService和一個類AccountService,AccountService類去繼承介面IAccountService並實現介面裡面的方法)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public interface IAccountService { int GetLst(); } public class AccountService: IAccountService { public int GetLst() { return 1; } }View Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class ValuesController : Controller { private readonly IAccountService _accountService; public ValuesController(IAccountService accountService) { _accountService = accountService; } [HttpGet] public dynamic GetAccount() { var result = this._accountService.GetLst(); return Ok(); } }View Code
六、使用NLog寫入文件日誌
新建配置文件命名為Nlog.config
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <!--寫入文件--> <target xsi:type="File" name="DebugFile" fileName="Logs\Debug\${shortdate}.log" layout="日誌時間:${longdate}${newline}日誌來源:${callsite}${newline}日誌級別:${uppercase:${level}}${newline}消息內容:${message}${newline}異常信息:${exception}${newline}==============================================================${newline}" > </target> <target xsi:type="File" name="InfoFile" fileName="Logs\Info\${shortdate}.log" layout="日誌時間:${longdate}${newline}日誌來源:${callsite}${newline}日誌級別:${uppercase:${level}}${newline}消息內容:${message}${newline}異常信息:${exception}${newline}==============================================================${newline}" > </target> <target xsi:type="File" name="ErrorFile" fileName="Logs\Error\${shortdate}.log" layout="日誌時間:${longdate}${newline}日誌來源:${callsite}${newline}日誌級別:${uppercase:${level}}${newline}消息內容:${message}${newline}異常信息:${exception}${newline}==============================================================${newline}" > </target> <rules> <logger name="FileLogger" minlevel="Debug" maxLevel="Debug" writeTo="DebugFile" /> <logger name="FileLogger" minlevel="Info" maxLevel="Info" writeTo="InfoFile" /> <logger name="FileLogger" minlevel="Error" maxLevel="Error" writeTo="ErrorFile" /> </rules> </nlog>View Code
在Startup類Configure方法中添加配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } #region NLog配置 loggerFactory.AddNLog(); // 添加NLog loggerFactory.ConfigureNLog($"{Directory.GetCurrentDirectory()}\\Nlog.config"); // 添加Nlog.config配置文件 loggerFactory.AddDebug(); #endregion }View Code
寫入日誌到文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class ValuesController : Controller { private readonly Logger _logger; public ValuesController() { _logger = LogManager.GetLogger("FileLogger"); } /// <summary> /// 寫入文件日誌 /// </summary> /// <returns></returns> [HttpGet] public dynamic WriteLogToFile() { _logger.Info("寫入Info文件"); _logger.Debug("寫入Debug文件"); _logger.Error("寫入Error文件"); return Ok(); } }View Code
七、使用NLog寫入資料庫日誌
添加依賴項:Microsoft.Extensions.Logging和NLog.Extensions.Logging
新建配置文件命名為Nlog.config
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <!--寫入資料庫--> <target xsi:type="Database" name="Database" connectionString="Data Source=.;Initial Catalog=MyDb;Persist Security Info=True;User ID=sa;Password=123456" commandText="insert into NLog_Log([CreateOn],[Origin],[LogLevel], [Message], [Exception],[StackTrace],[Desc]) values (getdate(), @origin, @logLevel, @message,@exception, @stackTrace,@desc)"> <!--日誌來源--> <parameter name="@origin" layout="${callsite}"/> <!--日誌等級--> <parameter name="@logLevel" layout="${level}"/> <!--日誌消息--> <parameter name="@message" layout="${message}"/> <!--異常信息--> <parameter name="@exception" layout="${exception}" /> <!--堆棧信息--> <parameter name="@stackTrace" layout="${stacktrace}"/> <!--自定義消息內容--> <parameter name="@desc" layout="${event-context:item=Desc}"/> </target> </targets> <rules> <logger name="DbLogger" levels="Trace,Debug,Info,Error" writeTo="Database"/> </rules> </nlog>View Code
同第六項代碼一樣,也是在Configure方法設置,寫入日誌到資料庫
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/// <summary> /// 將日誌寫入資料庫 /// </summary> /// <returns></returns> [HttpGet] public dynamic WriteLogToDb() { Logger _dblogger = LogManager.GetLogger("DbLogger"); LogEventInfo ei = new LogEventInfo(); ei.Properties["Desc"] = "我是自定義消息"; _dblogger.Info(ei); _dblogger.Debug(ei); _dblogger.Trace(ei); return Ok(); }View Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
USE [MyDb] GO /****** Object: Table [dbo].[NLog_Log] Script Date: 08/09/2018 17:13:20 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[NLog_Log]( [ID] [int] IDENTITY(1,1) NOT NULL, [Origin] [nvarchar](500) NULL, [LogLevel] [nvarchar](500) NULL, [Message] [nvarchar](500) NULL, [Desc] [nvarchar](500) NULL, [Exception] [nvarchar](500) NULL, [StackTrace] [nvarchar](500) NULL, [CreateOn] [datetime] NULL ) ON [PRIMARY] GOView Code
八、Nlog標簽解讀
NLog的使用方式基本上和其它的Log庫差不多,用於輸出日誌的級別包括:Trace,Debug,Info,Warn,Error,Fatal
<nlog>標簽 autoReload 修改配置文件後是否允許自動載入無須重啟程式 throwExceptions 內部日誌系統拋出異常 internalLogLevel 可選Trace|Debug|Info|Warn|Error|Fatal決定內部日誌的級別 Off 關閉 internalLogFile 把內部的調試和異常信息都寫入指定文件里 建議throwExceptions的值設為“false”,這樣由於日誌引發的問題不至於導致應用程式的崩潰。 <targets>標簽 <target />區域定義了日誌的目標或者說輸出 ,,在這裡可以按需設置文件名稱和格式,輸出方式。 name:自定義該target的名字,可供rule規則里使用 type: 定義類型,官方提供的可選類型有: Chainsaw|ColoredConsole |Console |Database|Debug|Debugger|EventLog|File|LogReceiverService|Mail|Memory|MethodCall|Network |NLogViewer|Null |OutputDebugString|PerfCounter|Trace|WebService 不過常用的還是 File \Database \Colored Console\ Maillayouts 用來規定佈局樣式,語法“${屬性}”,可以把上下文信息插入到日誌中,更多佈局渲染器可參考https://github.com/nlog/NLog/wiki/Layout%20Renderers
<rules>標簽
各種規則配置在logger里 name - 記錄者的名字 minlevel - 最低級別 maxlevel - 最高級別 level - 單一日誌級別 levels - 一系列日誌級別,由逗號分隔。 writeTo - 規則匹配時日誌應該被寫入的一系列目標,由逗號分隔。目前只整理了這些,後續會持續更新到這裡面,如有不合理的地方,請大家加以斧正,,,希望能和大家共同學習、共同進步,,
權責申明
作者:SportSky 出處: http://www.cnblogs.com/sportsky/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。如果覺得還有幫助的話,可以點一下右下角的【推薦】,希望能夠持續的為大家帶來好的技術文章!想跟我一起進步麽?那就【關註】我吧。