Доступ к настройкам из appsettings.json из библиотеки классов в Core 2.0

Я прочитал здесь дюжину вопросов по SO и как минимум 4 сообщения в блогах, но я не могу заставить это работать в решении VS2017 с несколькими проектами библиотеки классов. Однако я могу заставить его работать с решением с веб-приложением и одной библиотекой классов, хотя и с другим шаблоном, чем тот, который я нашел в документации и здесь, на SO.

Мое решение содержит 5 проектов: WebApplication, Testing, Infrastructure, Services, Domain (последние три являются библиотеками классов).

В проекте инфраструктуры я создал класс с именем EmailConfigurationSettings и зарегистрировал его в классе StartUp приложения WebApp.

Этот класс находится в библиотеке классов:

public class EmailConfigurationSettings
{
    public string Provider { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
}

Это в StartUp.cs в WebApp:

services.Configure<EmailConfigurationSettings>(Configuration.GetSection("EmailConfigurationSettings"));
services.AddOptions();

appsettings.json

"EmailConfigurationSettings": {
  "Provider": "gmail",
  "Username": "[email protected]",
  "Password": "mypassword" 
} 

Мне нужны настройки в проекте Services. Но пока я просто пытаюсь убедиться, что действительно могу их восстановить. Код ниже следует всем образцам кода, которые я нашел, но генерирует:

public class LoadEmailSettingsFromAppSettings
{
    private readonly IOptions<EmailConfigurationSettings> _emailSettings;

    public LoadEmailSettingsFromAppSettings(IOptions<EmailConfigurationSettings> emailSettings)
    {
        _emailSettings = emailSettings;
        Message = "Our provider is " + _emailSettings.Value.Provider;
    }

    public string Message { get; set; }
}

_emailSettings всегда имеет значение null

Итак, я попытался протестировать его в TestProject:

IOptions<EmailConfigurationSettings> someOptions = Options.Create<EmailConfigurationSettings>(new EmailConfigurationSettings());

Ну это тоже ноль.

В другом решении, с WebApp и одной библиотекой классов, используя немного другой шаблон, который я нашел в одном из блогов, я могу получить значения из appsettings.json:

public class AuthMessageSender : IEmailSender, ISmsSender
{
    public AuthMessageSender(IOptions<EmailConfig> emailSettings)
    {
        _emailSettings = emailSettings.Value;
    }

    public EmailConfig _emailSettings { get; }

    public Task SendEmailAsync(string email, string subject, string message)
    {
        Execute(email, subject, message).Wait();
        return Task.FromResult(0);
    }

Класс, заполненный из appsettings.json

Обратите внимание, что класс IOptions отличается 9 свойствами, но сконструирован так же, как в приведенном выше шаблоне.

Но использование этого шаблона не работает в проекте библиотеки с несколькими классами. Как я могу понять, как заставить это работать в сценарии с несколькими библиотеками классов?

Почему они отказались от ConfigurationManager я не знаю, это было намного проще.


person dinotom    schedule 09.10.2017    source источник


Ответы (2)


В микросервисах вы можете просто выполнить привязку к новому объекту, который соответствует определению json. Так бы ты поступил.

var emailConfig = new EmailConfigurationSettings();
Configuration.GetSection("EmailConfigurationSettings").Bind(emailConfig);
services.AddSingleton(emailConfig);

Как только вы это сделаете, все, что вам нужно сделать, это запросить копию EmailConfigurationSettings в конструкторе сервисных слоев. Это даст вам зависимость, введенную синглтоном этого объекта.

Я бы установил точку останова на «привязке» и убедился, что конфигурация электронной почты заполнена.

person willthiswork89    schedule 09.10.2017
comment
Запуск проекта с установкой точки останова на вызове AddSingleton (в StartUp.cs) приводит к нулевому значению emailConfig. так что это не работает, как и методы OP. - person dinotom; 10.10.2017
comment
Если это дает нулевой результат, значит, он неправильно загрузил конфигурацию своего приложения. Этот код взят из моего личного приложения mvc, поэтому я знаю, что он работает. Если вы установите переменную для возврата getsection, я буду спать, она возвращает null - person willthiswork89; 10.10.2017

Вот интересный ответ о библиотеке классов: библиотека классов.

В этой части вашего кода:

private readonly IOptions<EmailConfigurationSettings> _emailSettings;

public LoadEmailSettingsFromAppSettings(IOptions<EmailConfigurationSettings> emailSettings)
{
    _emailSettings = emailSettings;         

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

Где-то в вашем веб-приложении вы создаете LoadEmailSettingsFromAppSettings

public class SomeClass
{
    public SomeClass(IOptions<EmailConfigurationSettings> emailSettings) // dependency injection works in your webapp
    {
        var loadEmail = new LoadEmailSettingsFromAppSettings(emailSettings); // send EmailSettings to your other class in your class library

        //(...)
    }
}

И частный только для чтения должен быть:

public IOptions<EmailConfigurationSettings> EmailSettings {get; private set;}

только для чтения и свойства получения/установки

надеюсь понятно и полезно

person Sinan    schedule 10.10.2017