ASP.NET Core 中使用依赖注入 (DI) 容器获取并执行自定义服务

目录

[一、ASP.NET Core 中使用依赖注入 (DI) 容器获取并执行自定义服务](#一、ASP.NET Core 中使用依赖注入 (DI) 容器获取并执行自定义服务)

[1. app.Services](#1. app.Services)

[2. GetRequiredService()](#2. GetRequiredService())

[3. Init()](#3. Init())

二、应用场景

三、依赖注入使用拓展

1、使用场景

2、使用步骤

[1. 定义服务接口和实现类](#1. 定义服务接口和实现类)

[2. 注册服务到依赖注入容器](#2. 注册服务到依赖注入容器)

[3. 使用依赖注入获取并执行服务](#3. 使用依赖注入获取并执行服务)

[例子 1:在控制器中使用 DI 获取服务(控制器依赖注入)](#例子 1:在控制器中使用 DI 获取服务(控制器依赖注入))

[例子 2:在中间件中使用 DI 获取服务(中间件依赖注入)](#例子 2:在中间件中使用 DI 获取服务(中间件依赖注入))

[例子 3:在 Program.cs 中直接使用 DI 获取服务(项目启动获取服务)](#例子 3:在 Program.cs 中直接使用 DI 获取服务(项目启动获取服务))


一、ASP.NET Core 中使用依赖注入 (DI) 容器获取并执行自定义服务

今天看代码时候看到一句话,知识点接着学起来!!

复制代码
await app.Services.GetRequiredService<InitService>().Init();

这句话是在 ASP.NET Core 中使用依赖注入 (DI) 容器获取并执行某个服务的方法。

1. app.Services

appIApplicationBuilder 类型的对象,它用于配置请求处理管道。app.Services 获取的是 IServiceProvider,即服务提供者,用于解析和提供注册在依赖注入容器中的服务实例。

  • IServiceProviderASP.NET Core 中依赖注入(DI)机制的核心接口,用于从服务容器中解析已注册的服务。

2. GetRequiredService<InitService>()

GetRequiredService<T>()IServiceProvider 提供的方法,用于从 DI 容器中获取指定类型 T 的服务实例。

  • InitService 是某个自定义服务类(可能是应用程序启动时进行一些初始化操作的服务),通过 GetRequiredService<InitService>() 从 DI 容器中获取该服务的实例。

    • GetRequiredService<T>() 方法与 GetService<T>() 不同,它在容器中没有找到所请求的服务时,会抛出 InvalidOperationException 异常。相反,GetService<T>() 如果找不到服务,则会返回 null

3. Init()

InitService 类中有一个 Init 方法,它是一个自定义的方法,通常用于执行一些初始化任务(如数据库初始化、缓存加载、配置设置等)。

  • Init() 方法可能是一个异步方法,因此它被 await 关键字调用,表示它需要异步执行,执行完毕后,程序才能继续执行下去。

结合起来的含义

  • ASP.NET Core 的依赖注入容器中获取 InitService 实例。
  • 调用 InitService 中的 Init 方法来进行一些初始化工作。
  • 使用 await 关键字,确保初始化操作完成之后,才继续执行后续的代码。

二、应用场景

这行代码常常出现在 ASP.NET Core 应用的启动阶段,特别是在 Program.csStartup.cs 文件中,通常用于执行应用启动时需要的一些初始化任务。例如:

  • 初始化数据库。
  • 加载应用配置。
  • 设置缓存或其他外部资源。

思考:

从这句话中 我们可以大致猜测,有一个类 类里边有一个Init方法:

复制代码
public class InitService
{
    private readonly IMyDbContext _dbContext;

    public InitService(IMyDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task Init()
    {
        // 执行数据库初始化或其他启动任务
        await _dbContext.InitializeAsync();
    }
}

因此,我们在 Program.cs 中,你可以使用

await app.Services.GetRequiredService<InitService>().Init();

来确保在应用启动时执行该初始化操作:

复制代码
public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        // 注册服务
        builder.Services.AddScoped<InitService>();

        var app = builder.Build();

        // 在应用启动时执行初始化
        await app.Services.GetRequiredService<InitService>().Init();

        // 配置请求管道
        app.MapControllers();

        await app.RunAsync();
    }
}

三、依赖注入使用拓展

1、使用场景

ASP.NET Core 中,依赖注入(DI)是通过构造函数注入、属性注入或方法注入来实现的,通常我们会通过 IServiceProvider 来获取和执行某个服务。

一般有如下代码使用场景:

  • 构造函数注入:通过构造函数注入依赖的服务,最常见的 DI 方式。
  • 方法或属性注入:也可以使用方法或属性注入,但这些方法不如构造函数注入常见。
  • 中间件注入ASP.NET Core 中间件也可以通过构造函数注入来获取 DI 容器中的服务。
  • IServiceProvider 获取服务 :在一些情况下,可能需要在应用程序启动时或特定时刻获取服务,可以通过 IServiceProvider 来实现。

通过依赖注入,ASP.NET Core 提供了一个灵活且易于测试的架构,使得应用程序中的服务解耦并易于维护。

2、使用步骤

1. 定义服务接口和实现类

首先,我们定义一个简单的服务接口和它的实现类。

复制代码
// 定义服务接口
public interface IMyService
{
    Task ExecuteAsync(string message);
}

// 服务实现
public class MyService : IMyService
{
    public async Task ExecuteAsync(string message)
    {
        await Task.Delay(1000);  // 模拟一些异步操作
        Console.WriteLine($"Executing MyService with message: {message}");
    }
}

2. 注册服务到依赖注入容器

Startup.csProgram.cs 中,我们需要将服务注册到 DI 容器中。通常,这些注册是在 ConfigureServices 方法中进行的。

复制代码
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // 注册 IMYService 接口及其实现类 MyService
        services.AddSingleton<IMyService, MyService>();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // 省略其他中间件配置...
    }
}

3. 使用依赖注入获取并执行服务

假设我们在 ControllerMiddleware 中需要执行 IMyService,可以通过构造函数注入的方式获取服务并执行。

例子 1:在控制器中使用 DI 获取服务(控制器依赖注入)
复制代码
// Controller 示例
public class HomeController : Controller
{
    private readonly IMyService _myService;

    // 通过构造函数注入 IMyService
    public HomeController(IMyService myService)
    {
        _myService = myService;
    }

    public async Task<IActionResult> Index()
    {
        await _myService.ExecuteAsync("Hello from HomeController");
        return View();
    }
}
例子 2:在中间件中使用 DI 获取服务(中间件依赖注入)

ASP.NET Core 中,中间件也是可以使用 DI 来获取服务的。下面是如何在中间件中执行服务的一个例子:

复制代码
public class MyMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IMyService _myService;

    // 通过构造函数注入 IMyService
    public MyMiddleware(RequestDelegate next, IMyService myService)
    {
        _next = next;
        _myService = myService;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // 在中间件中执行 IMyService
        await _myService.ExecuteAsync("Hello from MyMiddleware");

        // 调用下一个中间件
        await _next(context);
    }
}

Startup.cs 中注册该中间件:

复制代码
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseMiddleware<MyMiddleware>();  // 注册自定义中间件
}
例子 3:在 Program.cs 中直接使用 DI 获取服务(项目启动获取服务)

在某些情况下,我们可能需要在应用启动时直接获取并执行某个服务。例如,在 Program.cs 文件中。

复制代码
public class Program
{
    public static async Task Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        // 获取 DI 容器中的服务并执行
        using (var scope = host.Services.CreateScope())
        {
            var myService = scope.ServiceProvider.GetRequiredService<IMyService>();
            await myService.ExecuteAsync("Hello from Program.cs");
        }

        await host.RunAsync();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}
相关推荐
zzzll11111 小时前
Spring Boot 实现数据脱敏:自定义注解 + Jackson 序列化器
java·spring boot·后端
戌中横1 小时前
数据持久化——PlayerPrefs
c#·数据持久化
2501_941875285 小时前
从配置中心到动态管理的互联网工程语法演进与多语言实践分享
开发语言·python
hfywmsj5 小时前
广州餐饮铺位招租决策模型:多因子选址系统设计
开发语言·人工智能·python·广州餐饮铺位招租
vx-Biye_Design5 小时前
SSM伴侣动物伴护星小程序06330-计算机课程设计、毕业设计
spring boot·后端·elasticsearch·小程序·架构·课程设计·idea
努力的lpp7 小时前
php反序列化一(大白话版)
开发语言·web安全·php·ctf·反序列化
2分钟速写快排7 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
菜鸟~noob2337 小时前
【电子战】第03篇:CFAR(恒虚警)处理【含matlab代码】
开发语言·matlab
面向Google编程7 小时前
Apache Iceberg Variant 类型:v3 半结构化数据不再「二选一」
大数据·后端
jason成都8 小时前
Spring WebFlux 适配达梦新方案|dm‑r2dbc:Netty 异步传输的实验性 R2DBC 驱动
java·后端·spring