ASP.NET Core 使用依赖注入访问其他服务

use*_*430 2 c# dependency-injection asp.net-core

这是 ASP.NET Core 默认项目ConfigureServices方法:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc();

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
}
Run Code Online (Sandbox Code Playgroud)

我的问题是如何访问 ApplicationDbContext 中的电子邮件服务或短信服务?

或者假设我将构建一个自定义服务,并像这样在 DI 中注册它:

services.AddTransient<ICustomService, CustomService>();
Run Code Online (Sandbox Code Playgroud)

我如何在其中访问电子邮件服务或短信服务?

我假设电子邮件和短信服务必须在其他服务使用它们之前添加到 DI 中,对吗?

Set*_*Set 6

ASP.NET Core 提供的默认 DI 实现仅支持构造函数注入。您的CustomService类应该具有ctor期望依赖项(短信/电子邮件发件人)作为参数:

public class CustomService : ICustomService
{
    public ClassName(IEmailSender emailSender, ISmsSender smsSender)
    {
        // use senders here or store in private variables
    }
}
Run Code Online (Sandbox Code Playgroud)

定义构造函数时,请注意(来自构造函数注入行为部分)

  • 构造函数注入要求有问题的构造函数是公共的。
  • 构造函数注入要求只存在一个适用的构造函数。支持构造函数重载,但只能存在一种重载,其参数都可以通过依赖注入实现。
  • 构造函数可以接受依赖注入未提供的参数,但这些参数必须支持默认值。

我假设电子邮件和短信服务必须在其他服务使用它们之前添加到 DI 中,对吗?

它们应该在 DI 容器中注册,然后才会尝试构造期望它作为构造函数参数的类的第一个实例。由于方法services.AddTransient<ICustomService, CustomService>();不实例化 CustomService 类,以下它仍然是一个有效的代码:

services.AddTransient<ICustomService, CustomService>();
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
Run Code Online (Sandbox Code Playgroud)

但是从简单到复杂的类型进行注册是一个很好的做法。