GOOGLE ADS

понедельник, 25 апреля 2022 г.

С# Внедрение определенного элемента из appSettings.json во время выполнения

Как внедрить конкретный параметр (возможно, многие) из массива appSettings.json в веб-API C#.NET Core на основе входного значения среды выполнения?

appSettings.json:

{
"SettingProfiles": [
{
"Name": "Profile1",
"SettingA": "SettingAValue1",
"SettingB": "SettingBValue1"
},
{
"Name": "Profile2",
"SettingA": "SettingAValue2",
"SettingB": "SettingBValue2"
}
...
}

Классы настроек:

public class Settings {
public List<SettingsProfile> SettingsProfiles { get; set; }
}
public class SettingsProfile {
public string Name { get; set; };
public string SettingA { get; set; };
public string SettingB { get; set; };
}

Класс обслуживания:

public class MyService: IMyService {
private readonly SettingsProfile _Profile;

public MyService(SettingsProfile profile) {
_Profile = profile;
}
public void DoStuff() {
Console.WriteLine($"Setting A: {_SettingsProfile.SettingA}, Setting B: {_SettingsProfile.SettingB}")
}
}

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

Я понимаю, что «обновлять» сервис было бы плохой практикой, хотя это единственный способ понять, как заставить его работать:

public class MyController {
private readonly Settings _Settings;
public MyController(Settings settings) {
_Settings = settings;
}
public IActionResult DoStuff(profileName) {
SettingsProfile profile = _Settings.Where(profile => profile.Name == profileName);
MyService service = new Service(profile);
}
}

Я, очевидно, что-то упускаю, но я смотрел видео на YouTube об инъекциях зависимостей и читал StackOverflow до крови, и еще не понял. Может ли кто-нибудь помочь мне с шаблоном, которому я должен следовать?


Решение проблемы

Вот как я думаю, это должно работать. Будет намного чище, если вы воспользуетесь другим шаблоном: Factory.

interface ISettingServiceFactory{
MyService GetService(string profileName);
}
class SettingServiceFactory: ISettingServiceFactory
{
MyService GetService(string profileName){
}
}

Теперь вы можете реализовать GetServiceдвумя способами.

Первый — создать новый, как вы сделали в контроллере, и это не так уж плохо, поскольку это цель фабрики. Таким образом, вы как бы перемещаете эту логику куда-то еще.

Второй был бы немного уродливее, но что-то вроде этого

interface ISettingServiceFactory{
MyService GetService(string profileName);
void SetCurrentProfile(SettingsProfile profile);
}
class SettingServiceFactory: ISettingServiceFactory
{
private IServiceProvider _serviceProvider;
private Settings _Settings;
public SettingServiceFactory(IServiceProvider serviceProvider,Settings settings){
_serviceProvider = serviceProvider;
_Settings = settings;
}
MyService GetService(string profileName){
var service = _serviceProvider.GetRequiredService<MyService>();
var profile = _Settings.Where(profile => profile.Name == profileName);
service.SetCurrentProfile(profile);
return service;
}
}

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

В обоих случаях вы вводите фабрику в контроллер.

 public MyController(ISettingServiceFactory settingServiceFactory) {
_settingServiceFactory= settingServiceFactory;
}
public IActionResult DoStuff(profileName) {
MyService service = _settingServiceFactory.GetService(profileName)
}

Комментариев нет:

Отправить комментарий

Laravel Datatable addColumn returns ID of one record only

Я пытаюсь использовать Yajra Datatable для интеграции DataTable на свой веб-сайт. Я смог отобразить таблицу, но столкнулся с проблемой. В по...