简体   繁体   English

将子选项数组中的 IOptions 注入服务

[英]Inject IOptions from array of sub-options to Service

I have a web service that posts data to a variety of different external servers, with a specific server to use specified by the incoming data to my API. New servers could be added at any time.我有一个 web 服务,该服务将数据发布到各种不同的外部服务器,并使用传入数据指定的特定服务器到我的 API。可以随时添加新服务器。

I have an appSettings.json like this:我有一个 appSettings.json 这样的:

"Settings": {
  "SomeSetting1": "Value",
  "SomeSetting2": "Value",
  "ExternalServers": [
    {
      "Name": "ServerA",
      "Address": "ServerAAddress"
    },
    ...
    {
      "Name": "ServerZ",
      "Address": "ServerZAddress"
    },
  ]
}

With the following support classes:具有以下支持类:

public class MySettings {
    public string SomeSetting1 { get; set; }
    public string SomeSetting2 { get; set; }
    public List<ExternalServerSettings> ExternalServers { get; set; } 
}

public class ExternalServerSettings {
    public string Name { get; set; }
    public string Address { get; set; }
}

I am injecting the full Settings in Startup.cs:我在 Startup.cs 中注入完整的设置:

services.Configure<MySettings>(mySettings => Configuration.GetSection("Settings").Bind(mySettings));

I am creating a new service that I only want to inject an instance of ExternalServerSettings .我正在创建一个新服务,我只想注入一个ExternalServerSettings的实例。

Currently I am doing this:目前我正在这样做:

public class MyService : IMyService
{
    private readonly ExternalServerSettings ServerSettings;

    public MyService(ExternalServerSettings serverSettings) {
        ServerSettings = serverSettings
    }
}

In my controller or another service I will select the specific server based on inputs to the Post method.在我的 controller 或其他服务中,我将 select 基于对 Post 方法的输入的特定服务器。

But previously I have created other services which are injecting settings with IOptions :但之前我已经创建了其他服务,这些服务正在使用IOptions注入设置:

public OtherService(IOptions<MySettings> mySettings)

//instead of...
public OtherService(MySettings mySettings)

The existential crisis I am having is that I am creating MyService knowing in advance that I would be selecting and injecting a specific object instead of using IOptions, but best practices dictate that I shouldn't know/care what is happening externally, and I would like to be able to create any Services consistently without worrying how they may be called.我遇到的生存危机是我在创建MyService时事先知道我会选择并注入特定的 object 而不是使用 IOptions,但最佳实践规定我不应该知道/关心外部发生的事情,我会喜欢能够始终如一地创建任何服务,而不必担心它们的调用方式。 Is my pattern OK or is there a way to do this while still utilizing IOptions ?我的模式可以吗?还是有办法在仍然使用IOptions的同时做到这一点?

I am very new C# web API and dependency injection, and I just want to make sure that I am following best practices for when I move to more complex projects.我是非常新的 C# web API 和依赖注入,我只是想确保在我转向更复杂的项目时遵循最佳实践。

Below is a work demo, you can refer to it.下面是一个工作演示,你可以参考它。

TopItemSettings TopItem设置

public class TopItemSettings
    {
        public const string Month = "Month";
        public const string Year = "Year";

        public string Name { get; set; }
        public string Model { get; set; }
    }

Put below into appsetting.json将下面放入appsetting.json

"TopItem": {
    "Month": {
      "Name": "Green Widget",
      "Model": "GW46"
    },
    "Year": {
      "Name": "Orange Gadget",
      "Model": "OG35"
    }
  }

Register month in the startup在启动时注册月份

 public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<TopItemSettings>(TopItemSettings.Month,
                                      Configuration.GetSection("TopItem:Month"));
            
            
            //services.Configure<TopItemSettings>(TopItemSettings.Year,
            //                                    Configuration.GetSection("TopItem:Year"));
            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "OPtions", Version = "v1" });
            });
        }

ValuesController值控制器

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    private readonly TopItemSettings _monthTopItem;
    public ValuesController(IOptionsSnapshot<TopItemSettings> namedOptionsAccessor)
    {
        _monthTopItem = namedOptionsAccessor.Get(TopItemSettings.Month);
    }
    public ContentResult OnGet()
    {
        return Content($"Month:Name {_monthTopItem.Name} \n" +
                       $"Month:Model {_monthTopItem.Model} \n\n");
    }
}

Result:结果:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM