Skip to content

依赖注入

基本概念

依赖注入(Dependency Injection,DI)是控制反转(Inversion of Control,IOC)思想的实现方式。依赖注入简化模块的组装过程,降低模块之间的耦合度。

依赖注入中对象的声明周期:

  • 瞬态(Transient):每次获取服务,都会创建一个新的对象;

  • 范围(Scoped):某个范围内,获取到的都是同一个对象,但是出了这个范围,获取到的就是新对象;

  • 单例(Singleton):在全局获取服务,获取到的都是同一个对象;

生命周期的使用

三种生命周期的使用场景:

  1. 如果 类无状态,建议使用 Singleton

  2. 如果 类有状态,且有 Scope 控制,建议为 Scoped,因为通常这种 Scoped 控制下的代码都是运行在同一个线程中,没有并发修改的问题;

  3. 瞬态不建议使用;

写代码之前,请先安装 Microsoft.Extensions.DependencyInjection 这个 Nuget 包。

瞬态

C#
ServiceCollection services = new ServiceCollection();
// 将 TestServiceImpl 声明为瞬态服务
services.AddTransient<TestServiceImpl>();

using (ServiceProvider sp = services.BuildServiceProvider())
{
    TestServiceImpl t1 = sp.GetService<TestServiceImpl>();
    t.Name = "sunny";
    t.SayHi();
  
    TestServiceImpl t2 = sp.GetService<TestServiceImpl>();
    Console.WriteLine(object.ReferenceEquals(t1, t2));		//false,说明t1和t2是两个对象
}

范围

C#
ServiceCollection services = new ServiceCollection();
// 将 TestServiceImpl 声明为范围
services.AddScoped<TestServiceImpl>();

using (ServiceProvider sp = services.BuildServiceProvider())
{
    using (IServiceScope scope = sp.CreateScope())
    {
        TestServiceImpl t1 = scope.ServiceProvider.GetService<TestServiceImpl>();
        TestServiceImpl t2 = scope.ServiceProvider.GetService<TestServiceImpl>();

        Console.WriteLine(object.ReferenceEquals(t1, t2));	// true,说明Scoped在using范围内是同一个对象
    }
}

单例3

C#
ServiceCollection services = new ServiceCollection();
// 将 TestServiceImpl 声明为单例
services.AddSingleton<TestServiceImpl>();

using (ServiceProvider sp = services.BuildServiceProvider())
{
    TestServiceImpl t1 = sp.GetService<TestServiceImpl>();
    t1.Name = "sunny";
    t1.SayHi();
    TestServiceImpl t2 = sp.GetService<TestServiceImpl>();
    t2.Name = "TOM";
    t2.SayHi();

    t1.SayHi(); // TOM
    Console.WriteLine(object.ReferenceEquals(t1, t2)); // true:t1和t2指向同一个地址,说明是在全局创建了一个对象
}

ServiceProvider()

ServiceProvider 类继承自 IServiceProvider,也可以当作是 IServiceProvider 的方法:

方法作用
GetService<T>()获取服务中的对象,若没有获取到,则返回null
GetService(Type serviceType)同上
GetRequiredService<T>()获取服务中的对象,若没有获取到,则直接报错
GetRequiredService(Type serviceType)同上
GetServices<T>()获取多个服务中的对象
C#
ServiceCollection services = new ServiceCollection();
services.AddScoped<ITestService, TestServiceImpl>();
services.AddScoped<ITestService, TestServiceImpl2>();

using (ServiceProvider sp = services.BuildServiceProvider())
{
    // GetService获取服务中的对象,若没有获取到,则返回null
    ITestService t1 = sp.GetService<ITestService>();
    ITestService t2 = (ITestService)sp.GetService(typeof(ITestService));

    // GetRequiredService获取服务中的对象,若没有获取到,则直接报错
    ITestService t3 = sp.GetRequiredService<ITestService>();
    ITestService t4 = (ITestService)sp.GetRequiredService(typeof(ITestService));

    // GetServices获取多个服务中的对象
    IEnumerable<ITestService> t5 = sp.GetServices<ITestService>();
    foreach (ITestService item in t5)
    {
        Console.WriteLine(item.GetType());
    }
}

Released under the MIT License.