理解ASP.NET Core 依赖注入

目录:web

1、什么是依赖注入cookie

1.一、什么是依赖?app

1.二、 什么是注入?async

1.三、依赖注入解决的问题ide

2、服务的生命周期(.Net Core DI)模块化

3、替换默认服务容器单元测试

  3.一、为何替换默认服务容器?学习

  3.二、如何替换服务容器测试


 

1、什么是依赖注入ui

一、 什么是依赖

Rely类

  public class Rely
    {
        public Task Test(string testMessage)
        {
            Console.WriteLine(testMessage);
            return Task.FromResult(0);
        }
  }

 

Output类

public class Output
    {
        Rely rely = new Rely();
        public async Task Out()
        {
            await rely.Test("這是一個測試消息");
        }
    }

Output类须要Rely类来帮助它实现输出的功能,这样Output类对Rely类产生了依赖,能够理解为Output依赖于Rely

依赖的一个设计原则:依赖于抽象,而不是具体的实现,这个后面会具体解释的

 

二、 什么是注入

修改Output类

public class Output
    {
        private Rely _rely;
        public Output(Rely rely)
        {
            _rely = rely;
        }
        public async Task Out()
        {
            await _rely.Test("這是一個測試消息");
        }
    }

在这里Output类不去实例化Rely类,而是经过其余人传递给我,我只用就好。到底怎么理解注入呢?

简单来讲就是别人对依赖建立实例化,我本身只负责使用,别人建立好了给我使用,这么一个过程能够理解为注入

这里主要体现了控制反转 (IoC)的思想,什么是IOC ?咱们看看下面的图就好理解了

 

 

 

直接依赖关系在运行的时候A调用B,B调用C,编译的时候A取决于B,B取决于C。

而在反转依赖关系中, A能够调用B实现的抽象上的方法,让A能够在运行时调用B,而B又在编译时依赖于A控制的接口,程序运行时流程跟直接依赖关系同样。可是插入了接口意味着能够轻松的有不一样实现

 

三、 依赖注入解决的问题

依赖注入主要体现了IOC思想,IOC将实现详细信息编写为依赖而且实现了更高级的抽象,所以程序测试性,维护性,模块化程度都更高了。这也就对应了刚刚的那个设计规则--依赖于抽象,而不是具体的实现。

那么依赖注入到底解决了哪些问题呢?

问题一:在直接依赖关系中若是A类须要更换为其余实现,那么就必须得修改B类

问题二:若是有多个依赖B类的类,那么将会实例化多个配置,这样代码会比较分散和冗余

问题三:这种实现方法很难实现单元测试

解决这些问题的办法:

一:使用了接口抽象话依赖关系的实现,改动实现只须要改动注入的地方便可

二:注册服务容器中的依赖关系,有多处须要不准多出实例化配置,直接在Startup.ConfigureServices中注册便可

 

2、服务的生命周期(.Net Core DI)

在.NET Core中DI的核心分为两个组件:IServiceCollection和 IServiceProvider。

    •   IServiceCollection---负责注册
    •   IServiceProvider---负责提供实例

 

Startup.csConfigureServices中注册服务

   public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

 
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();//单例生存期

            services.AddScoped<IHttpContextAccessor, HttpContextAccessor>();//范围生存期

            services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();//暂时生存期

 
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

 

一、 Transient暂时生存期)--暂时生存期服务是每次从服务容器进行请求时建立的。 这种生存期适合轻量级、 无状态的服务。

暂时生存期会在每次请求的时候建立一个实例

二、 Scoped范围生存期)--范围生存期服务是每一个客户端链接时建立的一次实例

范围生存期会在客户端链接时建立一次实例,而后每次请求的实例都是相同的

三、 Singleton单例生存期)--单例生存期会在程序第一次请求是建立一次实例

单例生存期仅会在第一次链接时建立一次实例,全部整个程序使用的实例都是同一个实例

 

3、替换默认服务容器

一、 为何替换默认服务容器

咱们能够首先理解下什么是服务容器—依赖注入把依赖的建立给了别人,别人建立好了再给咱们使用。那么在哪里建立依赖呢?或者说在那里管理依赖呢?这里就有了容器这个概念,负责管理系统中全部的依赖。

那么咱们为何要替换容器呢?

内置的服务容器足够实现一些小型的项目或知足大多数的消费者,可是遇到大型的项目就比较麻烦了,依赖较多,内置的服务容器就显得有点短板了。当咱们遇到这些问题的时候就能够考虑替换默认服务容器。

二、 如何替换服务容器

这里咱们说下替换服务容器为Autofac

安装适当的包

    •   Autofac
    •   Autofac.Extensions.DependencyInjection

在 Startup.ConfigureServices 中配置返回 为IServiceProvider:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    // Add other framework services
    // Add Autofac
    var containerBuilder = new ContainerBuilder();
    containerBuilder.RegisterModule<DefaultModule>();
    containerBuilder.Populate(services);
    var container = containerBuilder.Build();
    return new AutofacServiceProvider(container);

}

 

若是要使用第三方容器的话, Startup.ConfigureServices 必须返回 IServiceProvider。

而后咱们在 DefaultModule 中配置 Autofac

public class DefaultModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<CharacterRepository>().As<ICharacterRepository>();
    }
}

 

 

 


 

  欢迎你们扫描下方二维码,和我一块儿学习更多的知识😊

 

  

相关文章
相关标签/搜索