ASP. NET Core 3.1, внедряющий массив объектов из настроек приложения. json в внедренный сервис - PullRequest
1 голос
/ 01 апреля 2020

Я пытаюсь внедрить пару учетных записей электронной почты, которые есть в настройках приложения. json в службу электронной почты.

РЕДАКТИРОВАТЬ: Моему EmailRepository.cs требуется DbContext впрыскивается также. Я использовал ответ @Nkosi, который работал без необходимости использования DbContext. Я планирую использовать DbContextPool в производстве, так как мне использовать один из них в моем методе ConfigureServices?

appsettings. 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"
  }
]

SanSender .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();
    }
}

EmailRepository.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;
    }
}

Startup.cs:

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

    services.AddScoped<EmailRepository>();

    services.AddControllersWithViews();
}

Контроллер:

public class HomeController : Controller
{
    public HomeController(
        IOptions<List<SanSender>> optionsSanSenders, EmailRepository emailService)
    {
    }

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

В контроллере я добавил IOptions<List<SanSender>> optionsSanSenders, и я могу получить к ним доступ, но EmailService.cs находится в библиотеке классов, и я бы предпочел не добавлять к нему ненужные зависимости.

У EmailService действительно есть IEnumerable<SanSender> SanSenders, но он имеет нулевую длину / количество.

Что я делаю не так?

1 Ответ

1 голос
/ 01 апреля 2020

Изменить подход.

public class SanSenderOptions {
     public List<SanSender> SanSenders { get; set; }
}

Извлеките настройки из конфигурации, а затем зарегистрируйте их, где это необходимо.

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();
}

В хранилище будут разрешены инъекции отправителей.

Необходимо выполнить рефакторинг контроллера чтобы получить настроенные параметры.

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

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

}

Ссылка Конфигурация в ASP. NET Ядро

Ссылка Шаблон настроек в ASP. NET Core

...