使用AutoFac 2避免服务定位器

Pag*_*age 5 ioc-container autofac

我正在构建一个使用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<T>()
    {
        return _resolver.Resolve<T>();
    }
}
Run Code Online (Sandbox Code Playgroud)

从前一个问题的答案中,我找到了一种方法,通过使用自动生成的工厂来帮助减少在我的UnitOfWork中使用IoCHelper的需要.继续沿着这条路走下去,我很好奇我是否可以完全消除我的IoCHelper.

这是场景:

我有一个静态的Settings类,它作为我的配置实现的包装器.由于Settings类是对我的大多数其他类的依赖,因此包装器使我不必在整个应用程序中注入设置类.

Settings.cs

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

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<IConfigurationSettings>();
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在不使用服务定位器的情况下处理这个问题,而不必诉诸于将AppSettings注入到每个类中?下面列出了我继续依赖ServiceLocator而不是构造函数注入的3个方面:

  • 的AppSettings
  • 记录
  • 高速缓存

Pet*_*old 4

我宁愿注入IAppSettings到每个需要它的类中,只是为了让它们摆脱对Settings. 问题是,您真的需要将这种依赖关系散布到每个类中吗?

如果你真的想使用静态Settings类,我至少会尝试使其测试友好/可伪造。考虑一下:

public static class Settings
{
    public static Func<IAppSettings> AppSettings { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

以及在哪里构建容器:

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

Settings.AppSettings = () => container.Resolve<IAppSettings>();
Run Code Online (Sandbox Code Playgroud)

这将允许在测试期间更换假货:

Settings.AppSettings = () => new Mock<IAppSettings>().Object;
Run Code Online (Sandbox Code Playgroud)

现在,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"];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)