DependencyInjection组件实现IOC控制反转(2)

目的:讲解DependencyInjection组件实现IOC的步骤

1、添加Nuget包:Micosoft.Extensions.DependencyInjection

2、创建容器:

//创建容器
ServiceCollection services = new ServiceCollection();

 

3、注册:把服务注册进容器的过程

    有两个概念需要说明下:

         服务类型(service type):指用户根据什么类型来获取,服务类型可以时接口,也可以是类,建议使用接口,面向接口编程,更灵活

         实现类型(implementation type):指真正实现服务的类到底是什么

       注册时,可以服务类型和实现类型一致(两个一样的类),也可以服务类型是接口,实现类型是继承于接口的类

如下:IInterfaceA是一个接口,ImplementA是继承于接口IInterfaceA的类

 //服务类型和实现类型一致
 services.AddTransient<ImplementA,ImplementA>();
 //服务类型和实现类型不一致
 services.AddTransient<IInterfaceA, ImplementA>();

      当然,注册时还有很多重载方法,比如:AddTransient(Type serviceType,implementationType),AddTransient(Type  serviceType),AddTransient<Type  serviceType>()等等,自己查看文档就可以了

 

   我上面演示的注册都用了AddTransient只是为了方便说明注册的过程,实际上注册还要关注注册对象的生命周期,有以下三种:

    Transient:瞬态,每次获取容器相当与new一个新的对象

     Scoped:范围,在一个scope范围内是同个对象

    Singleton:单例,在整个应用程序中都是同个对象

 public interface IInterfaceA
 {
    string Name { get; set; }
     void DoSomething();
     
 }

 public class ImplementA : IInterfaceA
 {
     string IInterfaceA.Name { get; set; }

     void IInterfaceA.DoSomething()
     {
         Console.WriteLine("我是 ImplementA,继承于IInterfaceA");
     }
 }
static void Main(string[] args)
{
    //创建容器
    ServiceCollection services = new ServiceCollection();
    //注册
    //services.AddTransient<ImplementA>();//注册方式1:直接注册实现类
    services.AddTransient<IInterfaceA,ImplementA>();//注册方式2:注册服务类型和对应的实现类,推荐使用
}

 

4、获取容器中的对象,有两种方式:

     1)使用服务定位器(ServiceLocator),使用容器的BuildServiceProvider()方法获取ServiceProvider,通过ServiceProvider以下方法获取服务

        T  GetService<T>():如果获取不到服务,则返回null

        Object GetService(Type  serviceType):返回的是Object类型,使用时还需要进行类型转换,一般不用,除了在写框架时,通过反射拿到类型

       T GetRequiredService<T>():Required,必须的,如果获取不到服务,则抛异常,

      object GetRequiredService(Type serviceType):

      IEnumerable<T> GetServices<T>():适用于可能有很多满足条件的服务

      IEnumerable<object> GetServices(Type serviceType):

      注意,如果容器中注册了同个服务的多个实现类型,那么使用 GetService、GetRequiredService获取服务时,都是获取到最后注入容器的实现类型

      

 //使用服务定位方式获取容器对象
 using (ServiceProvider service = services.BuildServiceProvider())
 {
     service.GetRequiredService<IInterfaceA>();
     IInterfaceA a=  service.GetService<IInterfaceA>();
     a.DoSomething();
 }

   

     2)通过依赖注入的方式:一般是使用构造函数注入

          新建InterfaceB接口以及继承于改接口的类ImplementB:

      

public interface InterfaceB
{
    public string Name { get; set; }

   
}

public class ImplementB : InterfaceB
{
    public string Name { get; set; }
    public ImplementB()
    {
        this.Name = "Sam";
    }
}

       新建InterfaceC接口以及继承于改接口的类ImplementC,ImplementC通过构造器注入获取InterfaceB

public interface InterfaceC
{
    void DoSomething();
}

 public class ImplementC : InterfaceC
 {
     private readonly InterfaceB interfaceB;


     public ImplementC(InterfaceB interfaceB)//构造注入
     {
         this.interfaceB = interfaceB;
     }

     public void DoSomething()
     {
         Console.WriteLine($"B is {interfaceB.Name}");
     }
 }

Main函数如下:

static void Main(string[] args)
{
    //创建容器
    ServiceCollection services = new ServiceCollection();
    //注册
    services.AddScoped<InterfaceB, ImplementB>();
    services.AddScoped<InterfaceC, ImplementC>();


    //使用服务定位方式获取容器对象
    using (ServiceProvider service = services.BuildServiceProvider())
    {
        InterfaceC interfaceC = service.GetRequiredService<InterfaceC>();
        interfaceC.DoSomething();
    }
}

输出:

 可以看到,ImplementC类通过构造注入了接口InterfaceB,这种方式比使用服务定位器更简单,用户不需要写任何多余的代码

 

依赖注入有“传染性”:如果一个类是通过依赖注入创建的,那么这个类的构造函数中声明的所有服务类型的参数都会被DI赋值,本身这个类也可以注入到其它的服务中

      

     

 

posted @ 2023-12-16 23:40  上位机韩工  阅读(71)  评论(0)    收藏  举报