Как вы трансформируете опции asp netcore, прежде чем они станут доступны - PullRequest
1 голос
/ 27 сентября 2019

У меня есть такие варианты:

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<AppSettings> PluginFolders переведен (потому что он содержит символы подстановки)?Я пробовал 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>, как везде:

enter image description here

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

Хорошо.Я выяснил это, покопавшись в некоторых источниках компонентов 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, будет знать, что сначала нужно вызвать IConfigureOptions перед возвратом экземпляра IOptions - это неправильно.

Изменение порядка исправило это.

1 голос
/ 27 сентября 2019

Это больше похоже на то, чего вы пытаетесь достичь

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

Выше описано действие, используемое для настройки параметров определенного типа.Примечание. Они выполняются раньше всех.

Ссылка Использование служб DI для настройки параметров

...