• 把旧系统迁移到.Net Core 2.0 日记(2)


    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

  • 相关阅读:
    LeetCode【21】 Merge Two Sorted Lists
    LeetCode【2】Add two numbers
    LeetCode【125】Valid Palindrome
    LeetCode【9】Palindrome Number
    LeetCode【20】Valid Parentheses
    LeetCode【1】Two Sum
    LeetCode【8】string to integer(atoi)
    LeetCode【168】Excel Sheet Column Title
    lambda表达式
    UML类图
  • 原文地址:https://www.cnblogs.com/zitjubiz/p/net_core_daily_2.html
Copyright © 2020-2023  润新知