C# 在运行时从 appSettings.json 注入特定项目

C# Injecting Specific Item from appSettings.json at runtime

如何根据运行时输入值从 C# .NET Core Web API 中的数组 appSettings.json 注入特定设置(可能很多)?

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

服务class:

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 视频并阅读 Whosebug 直到我的眼睛流血,但我还没有弄明白。有人可以帮我制定一个我应该遵循的模式吗?

这就是我认为它应该工作的方式。 如果你使用另一种模式,它会更干净: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)
   }