Loading

.NET依赖注入

概念

服务:对象。
服务容器:负责注册服务和管理服务的容器。
查询服务:创建对象及关联对象。
对象生命周期:Transient(瞬态);Scoped(范围);Singleton(单例)。

.NET 中使用 DI

根据类型来获取和注册服务。可以分别指定服务类型和实现类型。这两者可能相同,也可能不同。服务类型可以是类,也可以是接口,建议面向接口编程,会更加灵活。

  1. 安装
Install-Package Microsoft.Extensions.DependencyInjection
  1. 引入命名空间
using Microsoft.Extensions.DependencyInjection;
  1. 使用流程
    SerivceCollection 注册服务-》创建 ServiceProvider-》向 ServiceProvider 获取服务。

基本使用:

ServiceCollection services = new ServiceCollection();
services.AddScoped<Class1>();

using (ServiceProvider sp =services.BuildServiceProvider())
{
    Class1 c =sp.GetService<Class1>();
    c.Name = "Test";
    c.SayHi();
}

超出using范围后,sp会被销毁。但是以已经通过sp获取到的服务还是可用的。
没添加scope时,AddScoped和AddSingleton效果一样(多次获取的服务可以用object.Euqals验证,是同一个对象)。不写Scope,默认有一个全局的Scoped

生命周期

  1. 使用serviceProvider。CreateScope()创建scope
ServiceCollection services = new ServiceCollection();
services.AddScoped<Class1>();
;
using (ServiceProvider sp =services.BuildServiceProvider())
{
   using (IServiceScope scope1 = sp.CreateScope())
    {
        //在scope中使用sp时,不能直接去用外层的sp,而是通过scope1.ServiceProvider 去取
        scope1.ServiceProvider.GetService<Class1>(); 
    }
}

在scope中使用sp时,不能直接去用外层的sp,而是通过scope1.ServiceProvider 去取
不同scope中获取的服务不是同一个对象,同一个scope中获取的服务是同一个对象。

  1. 如果一个服务类实现了IDisposable,那么在scope结束时,会自动调用Dispose销毁对象。因此不要在scope外部引用scope内部获取的服务。//TODO:Dispose实现需要做哪些工作
  2. 不要在长生命周期的对象中引用比他短的对象,否则会直接报异常。例如 Singleton 引用 Transient等
  3. 生命周期选择:类无状态,没有什么并发问题,建议为Singleton,如果类有状态,且有Scoped控制,建议为Scoped;使用Transient要谨慎。
  4. 注册服务的重载方法有很多。

服务定位器

服务类型与实现类型不一致的用法:

ServiceCollection services = new ServiceCollection();
services.AddScoped<Interface1, Class1>();//这一步目前自己注册,其他框架可能会自己注册,注册服务和使用服务不是同一个人
;
using (ServiceProvider sp = services.BuildServiceProvider())
{
    Interface1 i1 = sp.GetService<Interface1>();
    i1.Name = "A";
    i1.SayHi();
    Console.WriteLine(i1.GetType());
}

目前自己注册,自己获取服务。后续使用其他框架时,可能会框架自己注册,写代码时只用获取服务就行。

需要构造入参的类如何注册服务:

services.AddSingleton(typeof(Interface1), new Class1(123));

GetService 方法获取不到对象时,返回null;GetRequiredService 方法获取不到对象时,会抛出异常。IEnumerable GetServices 方法适合可能有很多满足条件的服务。

依赖注入

  1. 依赖注入是有“传染性”的,如果一个类的对象是通过DI创建的,那么这个类的构造函数中声明的所有服务类型的参数都会被DI赋值;但是如果一个对象是程序员手动创建的,那么这个对象就和DI没有关系,它的构造函数中声明的服务类型参数就不会被自动赋值。

  2. .NET的DI默认是构造函数注入。

posted @ 2024-02-28 23:33  sq800  阅读(16)  评论(0编辑  收藏  举报