【问题标题】:How do you transform asp netcore options before they are accessible在访问它们之前如何转换 asp 网络核心选项
【发布时间】:2020-01-27 23:25:40
【问题描述】:

我有这样的选择:

public class ApplicationSettings
{
    public string Title { get; set; }

    public string PluginFolders { get; set; }
}

还有这样的服务:

public interface IWildcardResolver
{
    string Resolve(string value);
}


public class WildcardResolver : IWildcardResolver
{
    private readonly IHostingEnvironment _hostingEnvironment;

    public WildcardResolver(IHostingEnvironment hostingEnvironment)
    {
        _hostingEnvironment = hostingEnvironment;
        AddWildcard("%contentRootPath%", _hostingEnvironment.ContentRootPath);
        AddWildcard("%webRootPath%", _hostingEnvironment.WebRootPath);
        AddWildcard("%environment%", _hostingEnvironment.EnvironmentName);
    }

    private readonly Dictionary<string, string> _hardWiredValues = new Dictionary<string, string>();

    /// <inheritdoc />
    public string Resolve(string value)
    {
        var sb = new StringBuilder(value);
        foreach (var pair in _hardWiredValues)
        {
            sb.Replace(pair.Key, pair.Value);
        }

        return sb.ToString();
    }

    public void AddWildcard(string name, string value)
    {
        if (_hardWiredValues.ContainsKey(name))
            throw new Exception($"A value for the wildcard {name} already exists.");

        _hardWiredValues.Add(name, value);
    }
}

如何确保在通过 DI 访问这些设置之前使用 IOptions&lt;AppSettings&gt; PluginFolders 进行翻译(因为它包含通配符)?我已经尝试过IConfigureOptions&lt;AppSettings&gt;IPostConfigureOptions&lt;AppSettings&gt;,但它们似乎都发生在一个为时已晚的阶段。就像我缺少 IPreConfigureOptions 或其他东西一样。

public class PluginManager
{
    private readonly IOptions<ApplicationSettings> _settings;

    public PluginManager(IOptions<ApplicationSettings> settings)
    {
        _settings = settings;
        // how do i get an instance here which makes sure that the ApplicationSettings.PluginPaths is already manipulated without doing it manually?
    }
}

这样做是可行的,但感觉就像我在与框架作斗争,因为我不能像其他任何地方一样使用IOptions&lt;AppSettings&gt;

【问题讨论】:

标签: c# asp.net-core options


【解决方案1】:

好的。我通过挖掘一些 microsoft 组件源找到了它。

这是解决方案:

public class ApplicationSettingsSetup : IConfigureOptions<ApplicationSettings>
{
    private readonly IWildcardResolver _wildcardResolver;

    public ApplicationSettingsSetup(IWildcardResolver wildcardResolver)
    {
        _wildcardResolver = wildcardResolver;
    }

    /// <inheritdoc />
    public void Configure(ApplicationSettings options)
    {
        options.PluginFolders = _wildcardResolver.Resolve(options.PluginFolders);
    }
}

注册:

services.AddTransient<IConfigureOptions<ApplicationSettings>, ApplicationSettingsSetup>();
services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));

之前我从配置中加载 AppSettings 并随后注册 IConfigurationOptions。不知何故,我假设创建 Options 的工厂会知道在返回 IOptions 实例之前首先调用IConfigureOptions - 这是错误的。

更改顺序修复它。

【讨论】:

  • 检查我提供的答案,这是文档中建议的另一种方法
【解决方案2】:

这看起来更符合您想要实现的目标

services.AddOptions<ApplicationSettings>()
    .Configure<IWildcardResolver>((options, wildcardResolver) => {
        options.PluginFolders = wildcardResolver.Resolve(options.PluginFolders);
        //...
    });

上面注册了一个用于配置特定类型选项的操作。注意:这些都是在所有之前运行的。

参考Use DI services to configure options

【讨论】:

  • 我最初有这个方法,但是如果你从配置文件中加载配置,那么走这条路就行不通了。最初使用旧的调用顺序,我认为不可能拦截配置值 - 我显然错了
猜你喜欢
  • 1970-01-01
  • 2021-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
  • 2021-01-10
相关资源
最近更新 更多