來源: SportSky
連結:http://www.cnblogs.com/sportsky/p/9400419.html
序言
使用.NET Core,團隊可以更容易專註的在.net core上工作。比如核心類庫(如System.Collections)的更改仍然需要與.NET Framework相同的活力,但是ASP.NET Core或Entity Framework Core可以更輕鬆地進行實質性更改,而不受向後相容性的限制。
.NET Core借鑒了.NET Framework的最佳實踐,並將軟體工程的最新進展結合在一起。
一、淺談Startup類
在ASP.NET Core應用程式中,使用一個按約定Startup命名的類Startup,在Program.cs中使用WebHostBuilderExtensions UseStartup
ConfigureServices方法:主要用於服務配置,比如依賴註入(DI)的配置,使用時該方法必須在Configure方法之前
Configure方法:用於應用程式響應HTTP請求,透過向IApplicationBuilder實體新增中介軟體元件來配置請求管道
二、自定義路由
在Startup類的Configure方法配置
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
}
三、跨域設定
在Startup類的ConfigureServices方法配置
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 essay-header
.AllowCredentials(); // Specify the processing of cookie
});
});
#endregion
services.AddMvc();
}
其中“AppDomain”這個名字是自定義的,大家可以根據自己的喜好定義不同的名字,配置完成之後,在控制器上面新增[EnableCors(“AppDomain”)]特性即可,如果要實現全域性的跨域設定,可以在Configure方法裡面配置app.UseCors(“AppDomain”),即能實現全域性的跨域設定
四、自定義讀取配置檔案資訊
這裡是寫的一個公共方法去讀取配置檔案appsettings.json
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
(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
(config.GetSection(key)) .BuildServiceProvider()
.GetService
>() .Value;
return appconfig;
}
}
///
/// 讀取配置檔案
///
///
[HttpGet]
public dynamic JsonConfig()
{
var jsonStr = JsonConfigurationHelper.GetAppSettings
return Ok(jsonStr);
}
///
/// 物體類
///
public class ConfigDTO
{
public dynamic name { get; set; }
}
{
“config”: {
“name”: “Core.Api”
}
}
截圖看效果
五、程式集批次依賴註入
我們都知道依賴註入主要是為了方便解耦,解除應用程式之間的依賴關係,在我看來DI、IOC這兩者差不多是一樣的,DI是從應用程式的角度而IOC是從容器的角度,它們主要是對同一件事情的不同角度的描述。
然而,,,,,,當我們專案業務比較多的時候,如果要實現多個業務的註入,通常方法是手動一個個的新增註入,這樣可能有點太繁瑣,所以就想到了利用反射實現批次註入,,,,,,
幫助類
public class RuntimeHelper
{
///
/// 獲取專案程式集,排除所有的系統程式集(Microsoft.***、System.***等)、Nuget下載包
///
///
public static IList
{
var list = new List
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
{
var list = new List
foreach (var assembly in GetAllAssemblies())
{
var typeInfos = assembly.DefinedTypes;
foreach (var typeInfo in typeInfos)
{
list.Add(typeInfo.AsType());
}
}
return list;
}
public static IList
{
var list = new List
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;
});
}
}
public static class ServiceExtension
{
///
/// 用DI批次註入介面程式集中對應的實現類。
///
///
///
///
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;
}
///
/// 用DI批次註入介面程式集中對應的實現類。
///
///
/// 介面程式集的名稱(不包含檔案副檔名)
/// 實現程式集的名稱(不包含檔案副檔名)
///
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;
}
}
在Startupl類的ConfigureServices方法中新增
// 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();
}
呼叫(Ps:Core.BLL這個類庫裡面分別有一個介面IAccountService和一個類AccountService,AccountService類去繼承介面IAccountService並實現介面裡面的方法)
public interface IAccountService
{
int GetLst();
}
public class AccountService: IAccountService
{
public int GetLst()
{
return 1;
}
}
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();
}
}
六、使用NLog寫入檔案日誌
新建配置檔案命名為Nlog.config
xsi:type=”File”
name=”DebugFile”
fileName=”LogsDebug${shortdate}.log”
layout=”日誌時間:${longdate}${newline}日誌來源:${callsite}${newline}日誌級別:${uppercase:${level}}${newline}訊息內容:${message}${newline}異常資訊:${exception}${newline}==============================================================${newline}” >
xsi:type=”File”
name=”InfoFile”
fileName=”LogsInfo${shortdate}.log”
layout=”日誌時間:${longdate}${newline}日誌來源:${callsite}${newline}日誌級別:${uppercase:${level}}${newline}訊息內容:${message}${newline}異常資訊:${exception}${newline}==============================================================${newline}” >
xsi:type=”File”
name=”ErrorFile”
fileName=”LogsError${shortdate}.log”
layout=”日誌時間:${longdate}${newline}日誌來源:${callsite}${newline}日誌級別:${uppercase:${level}}${newline}訊息內容:${message}${newline}異常資訊:${exception}${newline}==============================================================${newline}” >
在Startup類Configure方法中新增配置
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
}
寫入日誌到檔案
public class ValuesController : Controller
{
private readonly Logger _logger;
public ValuesController()
{
_logger = LogManager.GetLogger(“FileLogger”);
}
///
/// 寫入檔案日誌
///
///
[HttpGet]
public dynamic WriteLogToFile()
{
_logger.Info(“寫入Info檔案”);
_logger.Debug(“寫入Debug檔案”);
_logger.Error(“寫入Error檔案”);
return Ok();
}
}
七、使用NLog寫入資料庫日誌
新增依賴項:Microsoft.Extensions.Logging和NLog.Extensions.Logging
新建配置檔案命名為Nlog.config
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)”>
同第六項程式碼一樣,也是在Configure方法設定,寫入日誌到資料庫
///
/// 將日誌寫入資料庫
///
///
[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();
}
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]
GO
八、Nlog標簽解讀
NLog的使用方式基本上和其它的Log庫差不多,用於輸出日誌的級別包括:Trace,Debug,Info,Warn,Error,Fatal
autoReload 修改配置檔案後是否允許自動載入無須重啟程式
throwExceptions 內部日誌系統丟擲異常
internalLogLevel 可選Trace|Debug|Info|Warn|Error|Fatal決定內部日誌的級別 Off 關閉
internalLogFile 把內部的除錯和異常資訊都寫入指定檔案裡
建議throwExceptions的值設為“false”,這樣由於日誌引發的問題不至於導致應用程式的崩潰。
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 Mail
layouts 用來規定佈局樣式,語法“${屬性}”,可以把背景關係資訊插入到日誌中,更多佈局渲染器可參考https://github.com/nlog/NLog/wiki/Layout%20Renderers
各種規則配置在logger裡
name – 記錄者的名字
minlevel – 最低階別
maxlevel – 最高階別
level – 單一日誌級別
levels – 一系列日誌級別,由逗號分隔。
writeTo – 規則匹配時日誌應該被寫入的一系列標的,由逗號分隔。
目前只整理了這些,後續會持續更新到這裡面,如有不合理的地方,請大家加以斧正、共同進步。
●編號139,輸入編號直達本文
●輸入m獲取文章目錄
Web開發
更多推薦《18個技術類公眾微信》
涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。