将 IOptions 传递给 .Net 核心中间件类以进行 json 配置检索

Posted

技术标签:

【中文标题】将 IOptions 传递给 .Net 核心中间件类以进行 json 配置检索【英文标题】:Passing IOptions into .Net core middleware class for json config retrieval 【发布时间】:2017-01-22 06:57:28 【问题描述】:

我正在尝试根据 .net 核心中的Options pattern 使用强类型的 json 配置设置。到目前为止的所有示例都显示了将强类型设置类注入控制器是多么容易,但我需要在中间件类中使用它(与this question 非常相似,但在尝试过这种方式后我没有进一步前进)。

所以,设置:

mysettings.json


  "MySettings": 
    "Name": "Some Name from config",
    "Description": "Some Description from config"
  

mysettings.cs

public class MySettings

    public string Name  get; set;  = "Default name";

    public string Description  get; set;  = "Default description";

startup.cs

public void ConfigureServices(IServiceCollection services)

    services.AddMvc();

    // Add functionality to inject IOptions<T>
    services.AddOptions();

    // Add our Config object so it can be injected
    services.Configure<MySettings>(Configuration.GetSection("MySettings"));
    services.AddSingleton<IMySettingsService, MySettingsService>();

MysettingsService.cs

public class MysettingsService : IMysettingsService

    private MySettings mySettings  get; set; 

    public MysettingsService (MySettings _mySettings)
    
        mySettings = _mySettings.value;
    

    public string GetName()
    
        return mySettings.Name; 
    

如何实例化 MysettingsService.cs 并将 IOptions&lt;MySettings&gt; 注入到类构造函数中以便调用 GetName 方法?

【问题讨论】:

【参考方案1】:

几点:

上述类中缺少构造函数 - MysettingsService 您是否在 Startup 类中注册了 IMysettingsService 的实现? 注册实现时,您可以初始化MysettingsService,如下所示: services.AddSingleton&lt;IMysettingsService, MysettingsService &gt;(i =&gt; new MysettingsService ());

按照以下步骤操作:

确保您已在 ConfigurationBuilder 中注册您的 JSON 文件 - mysettings.json

定义我的设置

public class MySettings

    public string Name  get; set; 

    public string Description  get; set; 

定义MySettingsService

public class MySettingsService : IMySettingsService

    private readonly MySettings mySettings;

    public MySettingsService (IOptions<MySettings> _mySettings)
    
        mySettings = _mySettings.Value;
    

    public string GetName()
    
        return mySettings.Name; 
    

在启动中

services.Configure<MySettings>(this.Configuration.GetSection("MySettings"));
services.AddSingleton<IMySettingsService, MySettingsService >();

已编辑——我包含了你要遵循的实现

我创建了一个示例应用程序,它适用于我;请按照以下步骤操作:

细节很少。 我的应用名称是:SettingsApp

    创建设置文件 - mySettings.json - 包含内容

  "MySettings": 
    "Name": "Some Name from config",
    "Description": "Some Description from config"
  

    Startup中配置
public Startup(IHostingEnvironment env)

    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("mySettings.json", true, reloadOnChange: true)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.env.EnvironmentName.json", optional: true)
        .AddEnvironmentVariables();

    if (env.IsDevelopment())
    
        // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
        builder.AddApplicationInsightsSettings(developerMode: true);
    
    Configuration = builder.Build();

见行:

.AddJsonFile("mySettings.json", true, reloadOnChange: true)

    创建MySettings 对象以保存设置
namespace SettingsApp.Initialisations

    public class MySettings
    
        public string Name  get; set; 

        public string Description  get; set; 
    

注意:我使用命名空间SettingsApp.Initialisations 来保存这个文件。您可以根据您的应用程序结构选择任何一种。

    创建接口IMySettingsService
namespace SettingsApp.Services

    public interface IMySettingsService
    
        string GetName();
    

注意:我为此使用命名空间SettingsApp.Services

    实现接口-IMySettingsService
using SettingsApp.Initialisations;
using Microsoft.Extensions.Options;

namespace SettingsApp.Services

    public class MySettingsService : IMySettingsService
    
        private readonly MySettings mySettings;

        public MySettingsService(IOptions<MySettings> _mySettings)
        
            mySettings = _mySettings.Value;
        

        public string GetName()
        
            return mySettings.Name;
        
    

    添加选项并让系统知道您在Startup.ConfigureServices方法中的实现
// This method gets called by the run time. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)

    // Options
    services.AddOptions();
    services.Configure<MySettings>(this.Configuration.GetSection("MySettings"));
    services.AddSingleton<IMySettingsService, MySettingsService>();

    // Add framework services.
    services.AddApplicationInsightsTelemetry(Configuration);

    services.AddMvc();

注意包括所需的使用。

查看下面的代码以了解这是如何完成的:

// Options
services.AddOptions();
services.Configure<MySettings>(this.Configuration.GetSection("MySettings"));
services.AddSingleton<IMySettingsService, MySettingsService>();
    使用实现(我使用HomeController 进行测试。)
public class HomeController : Controller

    private IMySettingsService mySettingsService;

    public HomeController(IMySettingsService settingsService)
    
        mySettingsService = settingsService;
    

    public IActionResult Index()
    
        // Get the settings
        var name = mySettingsService.GetName();

        return View();
    

...
    查看结果:

【讨论】:

感谢您的帮助,但我已经完成了您提到的所有步骤。如何使用 MySettingsservice 的实例来调用 GetName 方法?特别是,我如何传入一个 IOptions 以满足构造函数? 如果以上都完成了——除了让配置知道 mysettings.json 文件(docs.asp.net/en/latest/fundamentals/configuration.html),我很想知道你在 我的设置服务?在那里放一个调试点,让我们知道注入的对象是什么? 谢谢。我刚刚意识到,如果我只使用它的接口,DI 会处理 MySettingsService 的构造函数。您的彻底实施有所帮助。 如果我在控制器中完成了所有工作,但我不这样做,那就太好了。我还需要将配置传递给所有子类。这可能会有点混乱【参考方案2】:

在较新版本的 .NET 中,上述绑定方法不再起作用。

我创建了一个有效的扩展方法:

    public static void AddSettings<T>(this IServiceCollection serviceCollection, IConfiguration configuration) where T : class, new()
    
        var settings = new T();
        configuration.Bind(typeof(T).Name, settings);
        serviceCollection.AddSingleton(settings);
    

像这样使用它:

services.AddSettings<LoggingSettings>(configuration);

完整示例:

        string pathToConfigFile = "c:\\config.json";
        IConfiguration configuration = new ConfigurationBuilder()
            .AddJsonFile(pathToConfigFile, optional: false, reloadOnChange: true)
            .Build();

        var services = new ServiceCollection()

        services.AddSingleton(configuration);

        services.AddSettings<ConnectionSettings>(configuration);
        services.AddSettings<LoggingSettings>(configuration);
        services.AddSettings<AutoCreateSettings>(configuration);

【讨论】:

以上是关于将 IOptions 传递给 .Net 核心中间件类以进行 json 配置检索的主要内容,如果未能解决你的问题,请参考以下文章

带有列表的 asp.net 核心 ioptions

将数据从视图传递到 dotnet 核心中的控制器

将模型传递给 asp-for | ASP.net 核心

我们可以将 Func<T,TResult> 传递给 .Net core 5 中的中间件来执行吗?

如何创建IOptions 来自T的自定义实例(不是通过DI)

asp.net 核心环境变量未传递给 vuejs 配置