AspnetCore中的依赖注入

目录

概念

AspnetCore中的依赖注入。

使用第三方依赖注入


概念

关于依赖注入的概念,网上已经有很多解释,这里不多复述。简单讲有点类似计划经济下的物资分配,啥都先进仓库,然后按需分配。下边给几个链接,以供参考:

Architectural principles | Microsoft Docs
https://docs.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/architectural-principles#dependency-inversion

Angular - Angular 中的依赖注入
https://angular.cn/guide/dependency-injection

Core Technologieshttps://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans

AspnetCore中的依赖注入。

话说,AspNetCore中的很多东西的初始化都比较复杂,比如创建Identity中的UserManager对象,我们看下构造函数:

        public UserManager(IUserStore<TUser> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<TUser> passwordHasher, IEnumerable<IUserValidator<TUser>> userValidators, IEnumerable<IPasswordValidator<TUser>> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<TUser>> logger);

这么多的参数,眼睛看花了没有?如果每个调用地方都new一下,会不会很崩溃?其实类似的东西还有很多,这可能就是为什么微软默认要在AspNetCore中加入依赖注入的原因吧!所以呢,这个依赖注入也很简单,主要实现了生命周期管理,及构造函数的注入方式。

因为实现简单,那用起来也简单。AspNetCore中,啥都放在StartUp.cs中,而且第三方组件提供商,一般都会写个IServiceCollection的扩展方法,并且在提供扩展方法中传递组件初始化所需的参数。

Log4net的初始化方法,里边生成了一个Log4NetProvider的实例。

public static ILoggerFactory AddLog4Net(this ILoggerFactory factory, Log4NetProviderOptions options)
		{
			factory.AddProvider(new Log4NetProvider(options));
			return factory;
		}

对于简单的对象,比如自己写的个class,可以直接调用相应的Add方法:

public void ConfigureServices(IServiceCollection services)
{
    

    services.AddScoped<IMyDependency, MyDependency>();
    services.AddScoped<IMyDependency2, MyDependency2>();

   
}

用的时候,就直接在构造函数里加上就是了:

public class IndexModel : PageModel
{
    private readonly ILogger _logger;
    private readonly IOperationTransient _transientOperation;
    private readonly IOperationSingleton _singletonOperation;
    private readonly IOperationScoped _scopedOperation;

    public IndexModel(ILogger<IndexModel> logger,
                      IOperationTransient transientOperation,
                      IOperationScoped scopedOperation,
                      IOperationSingleton singletonOperation)
    {
        _logger = logger;
        _transientOperation = transientOperation;
        _scopedOperation    = scopedOperation;
        _singletonOperation = singletonOperation;
    }

    public void  OnGet()
    {
        _logger.LogInformation("Transient: " + _transientOperation.OperationId);
        _logger.LogInformation("Scoped: "    + _scopedOperation.OperationId);
        _logger.LogInformation("Singleton: " + _singletonOperation.OperationId);
    }
}

不过,如果依赖够多话,相应的构造函数也要写得非常的冗长了,真是佩服了AspNetCore的这些设计者们的脑回路,可能是为了活跃开源社区,故意留下这么个坑,让别人来填充。好在,对于Web开发中留了一个HttpContext.RequestServices ,可以直接获取相应的对象,这还算有点良心。比如可以这样:

    public abstract class BaseController : Controller
    {
        protected ILogger Logger => HttpContext.RequestServices.GetService<ILogger>();

        public UserManager<ApplicationUser> UserManager => HttpContext.RequestServices.GetService<UserManager<ApplicationUser>>();
        public RoleManager<ApplicationRole> RoleManager => HttpContext.RequestServices.GetService<RoleManager<ApplicationRole>>();
        public SignInManager<ApplicationUser> SignInManager => HttpContext.RequestServices.GetService<SignInManager<ApplicationUser>>();

        public ApplicationDbContext DbContext => HttpContext.RequestServices.GetService<ApplicationDbContext>();
    }

至于符合内置依赖注入的服务怎么写,请参考官方文档,这里不赘述了。

使用第三方依赖注入

微软在自家文档里也提到依赖注入的一些高级概念,但就是没实现,这也验证了我前的想法,就是留点空间给下游厂商去发挥,只有大家一起玩才能带动一个生态链么(可惜,相像很美好,这些第三方的组件基本上都是不温不火):

  • Property injection 属性注入
  • Injection based on name 名称注入
  • Child containers 子容器
  • Custom lifetime management 自定义生存期管理
  • Func<T> support for lazy initialization 懒加载回调函数
  • Convention-based registration 基于约定的注册

日志框架一样,也给出一些不错的第三方项目: 

 本人接触得比较早的是Autofac,下边就简单介绍一下用Autofac默认的IOC容器。还有就是.Net Framework、NetCore 1.0、NetCore 2.0,NetCore 3.0的实现细节都不太一样,这里只举3.0的例子。

AspNetCore 3.X项目里都有一个Program类,这是Web应用的入口,在Main函数里加载Web运行的最基础环境,IOC容器的替换也是在这个地方,也就是将默认的ServiceProvidorFactory换成AutofacServiceProviderFactory:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
             .UseServiceProviderFactory(new AutofacServiceProviderFactory())//加上这一行
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

AutoFac增加了一个ConfigureContainer方法,这个方法用于额外的依赖项配置,在这里边注册依赖项用的AutoFac的方式,跟标准的ConfigureServices有所不同,因为本文只讲如何集成Autofac,所以对于具体的使用这里不多讲,想深入了解Autofac,请移步

Registering Components — Autofac 6.0.0 documentation
https://autofaccn.readthedocs.io/en/latest/register/index.html,

下边是ConfigureContainer方法的一个示例:

StartUp.cs

        public void ConfigureContainer(ContainerBuilder builder)
        {
            // Register your own things directly with Autofac here. Don't
            // call builder.Populate(), that happens in AutofacServiceProviderFactory
            // for you.
            //builder.RegisterModule(new MyApplicationModule());

            builder.RegisterType<Class>().PropertiesAutowired();
            builder.RegisterType<HomeController>().PropertiesAutowired();
        }

这里边有两行,分别注册一个自定义类Class和一个Controller,并且各自的依赖项都启用了属性注入。这里要注意的是,Controller类型需要在ConfigureServices中申明为Service:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().AddControllersAsServices();//调用AddControllersAsServices(),将Controller服务化,这样Autofac才可以访问。
            services.AddLogging(loggin=> {
                loggin.AddConsole();
                loggin.AddLog4Net();

            });
            
        }

将默认的依赖注入换Autofac就是这么简单啊。

附:

Class类

    public class Class
    {
        public ILogger<Class> Logger { get; set; }
        public void SayHello()
        {
            Logger.LogInformation("Hello World!");
        }
    }

HomeController类

public class HomeController : Controller
    {
        ILogger logger;
        public Class Test { get; set; }
        public HomeController(ILoggerFactory factory)
        {
            this.logger = factory.CreateLogger("Home");
        }
        public IActionResult Index()
        {
            Test.SayHello();
            return View();
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值