Asp.net core 的依赖注入

依赖注入(DI)是一种在类和其依赖关系之间实现控制反转(IOC)的技术.

这是MSDN上对依赖注入的解释,那么什么是控制反转呢?

控制反转

简单地说,就是本来需要你用程序代码控制的对象的创建和维护,现在都交给第三方。

依赖注入会通过以下方式实现:

  • 使用接口或基类将依赖关系实现抽象化。
  • 在服务容器中注册依赖关系。
  • 将服务注入。框架负责创建依赖关系的实例,并在不再需要时将其释放。

具体在Asp.net core中如何使用,下文将使用Asp.net core内置的依赖注入框架进行讲解。首先是

准备工作

框架有一下几个核心类型:

  • IServiceCollection。负责服务的注册
  • ServiceDescriptor。存储服务对象的描述信息
  • IServiceProvider。服务容器
  • IServiceScope。为对象圈定作用域

对象的生命周期:

  • 单例 Singleton
  • 作用域 Scoped
  • 瞬时 Transient

先准备三个类

//MySingletonService.cs
public interface ISingletonService { }
public class MySingletonService:ISingletonService
{
}

//MyScopedService.cs
public interface IScopedService{ }
public class MyScopedService:IScopedService
{
}

//MyTransientService.cs
public interface ITransientService { }
public class MyTransientService:ITransientService
{
}

服务注册

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        
        //*常规注册不同生命周期的服务
        builder.Services.AddSingleton<ISingletonService, MySingletonService>();
        builder.Services.AddScoped<IScopedService, MyScopedService>();
        builder.Services.AddTransient<ITransientService, MyTransientService>();
        //注册泛型
        builder.Services.AddScoped(typeof(IScopedTService), typeof(MyScopedTService));
        
        //尝试注册,避免相同服务重复注册
        builder.Services.TryAddScoped<IScopedService, MyScopedService>();
        //尝试注册,同一接口注册多个实例
        builder.Services.TryAddEnumerable(ServiceDescriptor.Scoped<IScopedService, MyScopedService2>);
        
        //移除注册
        builder.Services.RemoveAll<IScopedService>();
        //替换第一个注册
        builder.Services.Replace(ServiceDescriptor.Singleton<IScopedService,MyScopedService>());
        
		builder.Services.AddEndpointsApiExplorer();
        builder.Services.AddSwaggerGen();
            
        var app = builder.Build();

        if (app.Environment.IsDevelopment())
        {
            app.UseSwagger();
            app.UseSwaggerUI();
        }
            
        app.UseAuthorization();
        
        app.MapControllers();

        app.Run();
    }
}

服务注入

这里介绍三种方式,推荐一般使用第一种,构造函数注入

[ApiController]
[Route("[controller]/[action]")]
public class DIController : ControllerBase
{
    //注册单个实例
    private readonly IScopedService _scopedService;

    public DIController(IScopedService scopedService)
    {
        _scopedService = scopedService;
    }
    
    //注册多个实例
    private readonly IEnumerable<IScopedService> _scopedServices;

    public DIController(IEnumerable<IScopedService> scopedServices)
    {
        _scopedServices = scopedServices;
    }

    [HttpGet]
    public void Test()
    {
        var s = _scopedServices.ToArray();
        Console.WriteLine(s[0].GetHashCode());
        Console.WriteLine(s[1].GetHashCode());
    }
}

如果一个类中只有某一个方法用到该服务,那么可以使用第二种

[HttpGet]
public void Test([FromServices] IScopedService _scopedService)
{
            
}

最后一种直接从容器中获取实例,一般不使用。但有些情况,比如要在一个单例服务中使用一个scoped服务,由于被注入服务生命周期更长依赖注入失败,此时可以使用

private readonly IServiceProvider _serviceProvider;

public DIController(IServiceProvider serviceProvider)
{
    _serviceProvider = serviceProvider;
}

[HttpGet]
public void Test()
{
    using (var scope = _serviceProvider.CreateScope())
	{
        var service = scope.ServiceProvider.GetRequiredService<IScopedService>();
    }
}
posted @   shanawdj  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示