我有这样的选择:
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);
}
}
[如何确定在使用IOptions<AppSettings>
通过PluginFolders通过DI访问那些设置之前(因为它包含通配符)?我已经尝试过IConfigureOptions<AppSettings>
和IPostConfigureOptions<AppSettings>
,但是它们似乎都发生在一个阶段太晚了。就像我缺少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<AppSettings>
:
确认。我通过浏览一些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
。我以某种方式假设创建Option的工厂会在返回IOptions实例之前先调用IConfigureOptions
-这是错误的。
更改订单已解决。
这看起来更符合您要实现的目标
services.AddOptions<ApplicationSettings>()
.Configure<IWildcardResolver>((options, wildcardResolver) => {
options.PluginFolders = wildcardResolver.Resolve(options.PluginFolders);
//...
});
上面注册了一个用于配置特定类型选项的操作。注意:它们先运行。