ASP.NET Core 3.1 将 appsettings.json 中的对象数组注入到注入的服务中

Mic*_*ida 6 c# dependency-injection asp.net-core-3.1

我正在尝试将 appsettings.json 中的几个电子邮件帐户注入到电子邮件服务中。

编辑:我也EmailRepository.cs需要注射。DbContext我使用了 @Nkosi 的答案,它无需 DbContext 即可工作。我计划DbContextPool在生产中使用,那么如何在我的方法中取出其中之一呢ConfigureServices

应用程序设置.json:

"SanSenders": [
  {
    "Host": "mail.theFourSeasons.com",
    "FromName": "The Four Seasons",
    "IsNoReply": true,
    "IsSssl": true,
    "Password": "tooGoodToBeTrue",
    "Port": 465,
    "Username": "noreply@theFourSeasons.com"
  },

  {
    "Host": "mail.theFourSeasons.com",
    "FromName": "Franki",
    "IsNoReply": false,
    "IsSssl": true,
    "Password": "cantTakeMyEyesOffYou",
    "Port": 465,
    "Username": "franki@theFourSeasons.com"
  }
]
Run Code Online (Sandbox Code Playgroud)

SanSender.cs:

"SanSenders": [
  {
    "Host": "mail.theFourSeasons.com",
    "FromName": "The Four Seasons",
    "IsNoReply": true,
    "IsSssl": true,
    "Password": "tooGoodToBeTrue",
    "Port": 465,
    "Username": "noreply@theFourSeasons.com"
  },

  {
    "Host": "mail.theFourSeasons.com",
    "FromName": "Franki",
    "IsNoReply": false,
    "IsSssl": true,
    "Password": "cantTakeMyEyesOffYou",
    "Port": 465,
    "Username": "franki@theFourSeasons.com"
  }
]
Run Code Online (Sandbox Code Playgroud)

电子邮件存储库.cs:

public class SanSender
{
    public string FromName { get; set; }
    public string Host { get; set; }
    public bool IsNoReply { get; set; }
    public bool IsSsl { get; set; }
    public string Password { get; set; }
    public int Port { get; set; }
    public string Username { get; set; }

    public async Task<bool> SendEmailAsync(
        string toAddress, string subject, string htmlMessage)
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

启动.cs:

public class EmailRepository
{
    public IEnumerable<SanSender> SanSenders { get; set; }

    //Edit: I need a DbContext injected as well.
    public EmailRepository(ApplicationDbContext applicationDbContext,  
        IEnumerable<SanSender> sanSenders)
    {
         SanSenders = sanSenders;
    }
}
Run Code Online (Sandbox Code Playgroud)

控制器:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<List<SanSender>>((settings) =>
    {
        Configuration.GetSection("SanSenders").Bind(settings);
    });

    services.AddScoped<EmailRepository>();

    services.AddControllersWithViews();
}
Run Code Online (Sandbox Code Playgroud)

在我添加的控制器中IOptions<List<SanSender>> optionsSanSenders,我可以在那里访问它们,但EmailService.cs在类库中,我宁愿不添加不必要的依赖项。

EmailService 确实有IEnumerable<SanSender> SanSenders,但它的长度/计数为零。

我究竟做错了什么?

Nko*_*osi 7

改变方法。

public class SanSenderOptions {
     public List<SanSender> SanSenders { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

从配置中提取设置,然后在需要的地方注册它们

public void ConfigureServices(IServiceCollection services) {
    SanSender[] senders = Configuration.GetSection("SanSenders").Get<SanSender[]>();

    services.Configure<SanSenderOptions>(options => {
        options.SanSenders = senders.ToList();
    });

    services.AddScoped<EmailRepository>(sp => 
        new EmailRepository(sp.GetRequiredService<ApplicationDbContext>(), senders));

    services.AddControllersWithViews();
}
Run Code Online (Sandbox Code Playgroud)

存储库将使注入的发件人得到解析。

应重构控制器以获得配置的选项。

public class HomeController : Controller {
    public HomeController(IOptions<SanSenderOptions>> optionsSanSenders, 
          EmailRepository emailService) {
        var senders = options.Value.SanSenders; //<--
    }

    public IActionResult Index() {
        return View();
    }

}
Run Code Online (Sandbox Code Playgroud)

ASP.NET Core 中的参考配置

参考ASP.NET Core 中的选项模式