Предотвращение сервисного локатора с AutoFac 2

Я создаю приложение, которое использует AutoFac 2 для DI. Я читал, что использования статического IoCHelper (Сервисный Локатор) нужно избежать.

IoCHelper.cs

public static class IoCHelper
{
    private static AutofacDependencyResolver _resolver;

    public static void InitializeWith(AutofacDependencyResolver resolver)
    {
        _resolver = resolver;
    }

    public static T Resolve()
    {
        return _resolver.Resolve();
    }
}

От ответов до предыдущего вопроса я нашел способ помочь уменьшить потребность в использовании моего IoCHelper в моем UnitOfWork с помощью Автоматически сгенерированных Фабрик. Продолжая вниз этот путь, мне любопытно, если я могу полностью устранить свой IoCHelper.

Вот сценарий:

У меня есть статический класс Настроек, который служит оберткой вокруг моей реализации конфигурации. Так как класс Настроек является зависимостью большинству моих других классов, обертка мешает мне иметь для введения класса настроек на всем протяжении моего приложения.

Settings.cs

public static class Settings
{
    public static IAppSettings AppSettings
    {
        get
        {
            return IoCHelper.Resolve();
        }
    }
}

public interface IAppSettings
{
    string Setting1 { get; }
    string Setting2 { get; }
}

public class AppSettings : IAppSettings
{
    public string Setting1
    {
        get
        {
            return GetSettings().AppSettings["setting1"];
        }
    }

    public string Setting2
    {
        get
        {
            return GetSettings().AppSettings["setting2"];
        }
    }

    protected static IConfigurationSettings GetSettings()
    {
        return IoCHelper.Resolve();
    }
}

Существует ли способ обработать это, не используя сервисный локатор и не имея необходимость обращаться к введению AppSettings в каждый класс? Упомянутый ниже эти 3 области, в которых я продолжаю полагаться на ServiceLocator вместо инжекции конструктора:

  • AppSettings
  • Вход
  • Кэширование

5
задан Community 23 May 2017 в 10:29
поделиться

1 ответ

Я бы предпочел ввести IAppSettings в каждый класс, которому он нужен, просто чтобы уберечь их от скрытой зависимости от Настройки . Вопрос в том, действительно ли вам нужно добавить эту зависимость в каждый класс?

Если вы действительно хотите использовать статический класс Настройки , я бы хотя бы попытался сделать его удобным для тестирования / подделывать . Подумайте об этом:

public static class Settings
{
    public static Func<IAppSettings> AppSettings { get; set; }
}

И где вы создаете свой контейнер:

var builder = new ContainerBuilder();
...
var container = builder.Build();

Settings.AppSettings = () => container.Resolve<IAppSettings>();

Это позволит заменять фейки во время теста:

Settings.AppSettings = () => new Mock<IAppSettings>().Object;

Теперь класс AppSettings (который, как я предполагаю, есть только один из) вы можете использовать обычную инъекцию конструктора. Я также предполагаю, что вы действительно хотите выполнять разрешение при каждом вызове свойств ваших настроек, тем самым внедряя фабричный делегат, который при необходимости извлекает экземпляр. Если в этом нет необходимости, вы, конечно, должны напрямую внедрить службу IConfigurationSettings .

public class AppSettings : IAppSettings
{
    private readonly Func<IConfigurationSettings> _configurationSettings;

    public AppSettings(Func<IConfigurationSettings> configurationSettings)
    {
        _configurationSettings = configurationSettings;
    }

    public string Setting1
    {
        get
        {
            return _configurationSettings().AppSettings["setting1"];
        }
    }

    public string Setting2
    {
        get
        {
            return _configurationSettings().AppSettings["setting2"];
        }
    }
}
4
ответ дан 15 December 2019 в 00:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: