把舊系統遷移到.Net Core 2.0 日記(2) - 依賴注入/日志NLog


Net Core 大量使用依賴注入(Dependency Inject), 打個比方,我們常用的日志組件有Log4Net,NLog等等.

如果我們要隨時替換日志組件,那么代碼中就不能直接引用某個組件的內容,也不能直接New 某個組件.

而是應該定義一組接口, 然后包裝各個組件,實現這個接口. Net Core 自帶組件容器, 啟動程序時,指定接口對應的實現.

然后在各個Controller 里, 通過構造函數的參數,把要帶過去的接口,把容器里的對象自動傳過去

在cshtml view頁面,要使用@inject方法, 例如在頁面使用Session,就要@inject IHttpContextAccessor _httpContextAccessor

@inject CRM.PermissionLogic  plogic
@inject IHttpContextAccessor _httpContextAccessor
@{int userid =(int)_httpContextAccessor.HttpContext.Session.GetInt32("UserId");}

 如果要在靜態類里使用,則要用到ServiceProvider, 在Startup.cs里注入,然后再用 serviceProvider.GetService<XXX>();

public void ConfigureServices(IServiceCollection services)
{
            //注入
            services.AddSingleton<IPageHeadBuilder, PageHeadBuilder>();

            //解析依賴 對於一個服務A來說,它可能並不是獨立的,它還在依賴服務B和服務C,而服務B又依賴服務D和服務E。。
            //一個合格的容器得再我們需要服務A時,能夠正確的解析這個依賴鏈,並按照正確的順序實例化並返回服務A。
            //ServiceProvider是ASP.NET Core團隊提供的默認的依賴注入容器。
            LayoutExtension.serviceProvider= services.BuildServiceProvider();
}
    public static class LayoutExtension
    {
        public static IServiceProvider serviceProvider { get; set; } //定義一個IServiceProvider

        public static IPageHeadBuilder GetService()
        {
            return serviceProvider.GetService<IPageHeadBuilder>();
        }
        
        public static void SetActiveMenuItemSystemName(this IHtmlHelper html, string systemName)
        {
            var head = GetService();
            head.SetActiveMenuItemSystemName(systemName);
        }
        
        public static string GetActiveMenuItemSystemName(this IHtmlHelper html)
        {
            var head = GetService();
            return head.GetActiveMenuItemSystemName();
        }
}

 

 

各個頁面/Controller ,再調用接口的方法. 所謂的面向接口編程.

Net Core 在Microsoft.Extension.Logging定義了ILogger,ILoggerFactory,ILoggerProvider 這幾個接口, 日志組件實現這個接口就可以被調用了.

上網查了一下,NLog已經實現了這些接口了,你用Nuget找NLog.Web.AspNetCore 就已經包裝好了. 具體文檔,請看這篇文章,非常詳細.

https://github.com/NLog/NLog.Web/wiki/Getting-started-with-ASP.NET-Core-2

我們來看一下代碼, 要調用NLog, 在Program.cs里

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                   .ConfigureLogging((hostingContext, logging) =>
                   {
                       logging.AddConsole();
                       logging.AddDebug();
                   })
                   .UseNLog()
                .Build();
    }

調用NLog寫Log,   在構造函數里增加參數,類型是接口,不能是實現類

using Microsoft.Extensions.Logging;    

public class HelloMiddleware { private readonly ILogger<HelloMiddleware> _logger; private readonly RequestDelegate _next; public HelloMiddleware(RequestDelegate next,ILogger<HelloMiddleware> logger) { _next = next; _logger = logger; } public Task Invoke(HttpContext httpContext) { httpContext.Response.WriteAsync("Hello in Class Invoke"+ Environment.NewLine); _logger.LogInformation("******hello middleware*********"); return _next(httpContext); } }

MVC的controller寫法也類似

        private readonly CRMContext _context;
        private readonly IConfiguration _config;
        private readonly ILogger<AccountController> _logger;

        public AccountController(CRMContext context
            IConfiguration configuration,ILogger<AccountController> logger)
        {
            _context = context;
            _config = configuration;
            _logger = logger;
        }

我們也可以把常用的注入(例如數據庫 CRMContext context ) 放在基類BaseController, 子類的構造函數繼承基類的構造函數

        private readonly IConfiguration _config;
        private readonly ILogger<AccountController> _logger;

        public AccountController(
            IConfiguration configuration,ILogger<AccountController> logger):base(context)
        {

            _config = configuration;
            _logger = logger;
        }
 public abstract class BaseController : Controller
{
        protected readonly CRMContext _context;

        public BaseController(CRMContext context)
        {
            _context = context;
        }
}

 

我們來看看UseNLog()這個方法的代碼,看看做了什么

        /// <summary>
        /// Use NLog for Dependency Injected loggers. 
        /// </summary>
        public static IWebHostBuilder UseNLog(this IWebHostBuilder builder)
        {
            return UseNLog(builder, null);
        }

        /// <summary>
        /// Use NLog for Dependency Injected loggers. 
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="options">Options for logging to NLog with Dependency Injected loggers</param>
        /// <returns></returns>
        public static IWebHostBuilder UseNLog(this IWebHostBuilder builder, NLogAspNetCoreOptions options)
        {
            if (builder == null) throw new ArgumentNullException(nameof(builder));
            options = options ?? NLogAspNetCoreOptions.Default;

            builder.ConfigureServices(services =>
            {
                //note: when registering ILoggerFactory, all non NLog stuff and stuff before this will be removed
                services.AddSingleton<ILoggerProvider>(serviceProvider =>
                {
                    ServiceLocator.ServiceProvider = serviceProvider;
                    return new NLogLoggerProvider(options);
                });

                //note: this one is called before  services.AddSingleton<ILoggerFactory>
                if (options.RegisterHttpContextAccessor)
                {
                    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
                }

                RegisterHiddenAssembliesForCallSite();
            });
            return builder;
        }

 

而Log4Net 就沒有官方的包裝,只有一個第三方包裝的, 但包裝的不好, 日志的配置不是放在Program.cs, 而是放在StartUp.cs. 我打算有時間再重新包裝一次.

參考這篇文章

http://www.cnblogs.com/drivenwinder/p/8300881.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM