5

我正在构建一个使用 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>();
    }
}

从对上一个问题的回答中,我找到了一种通过使用自动生成的工厂来帮助减少在我的 UnitOfWork 中使用 IoCHelper 的方法。继续走这条路,我很好奇我是否可以完全消除我的 IoCHelper。

这是场景:

我有一个静态 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>();
    }
}

有没有办法在不使用服务定位器的情况下处理这个问题,也不必求助于将 AppSettings 注入每个类?下面列出了我一直依赖 ServiceLocator 而不是构造函数注入的 3 个领域:

  • 应用设置
  • 日志记录
  • 缓存
4

1 回答 1

4

我宁愿注入IAppSettings每个需要它的类,只是为了让它们免受对Settings. 问题是,你真的需要把这种依赖洒到每一个类中吗?

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

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"];
        }
    }
}
于 2010-04-29T14:30:06.087 回答