避免使用AutoFac 2服务定位器 [英] Avoiding Service Locator with AutoFac 2

查看:110
本文介绍了避免使用AutoFac 2服务定位器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个将AutoFac 2用于DI的应用程序.我一直阅读,应该使用静态IoCHelper(服务定位器)避免.

I'm building an application which uses AutoFac 2 for DI. I've been reading that using a static IoCHelper (Service Locator) should be avoided.

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>();
    }
}

从答案到上一个问题,我找到了一种方法,可以通过使用

From answers to a previous question, I found a way to help reduce the need for using my IoCHelper in my UnitOfWork through the use of Auto-generated Factories. Continuing down this path, I'm curious if I can completely eliminate my IoCHelper.

这是场景:

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

I have a static Settings class that serves as a wrapper around my configuration implementation. Since the Settings class is a dependency to a majority of my other classes, the wrapper keeps me from having to inject the settings class all over my application.

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个领域:

Is there a way to handle this without using a service locator and without having to resort to injecting AppSettings into each and every class? Listed below are the 3 areas in which I keep leaning on ServiceLocator instead of constructor injection:

  • AppSettings
  • 记录
  • 缓存

推荐答案

我宁愿将IAppSettings注入到每个需要它的类中,只是为了使它们与对Settings的隐藏依赖关系保持一致.问题是,您真的需要将这种依赖性散布到每个班级吗?

I would rather inject IAppSettings into every class that needs it just to keep them clean from the hidden dependency on Settings. Question is, do you really need to sprinkle that dependency into each and every class?

如果您真的想使用静态Settings类,那么我至少会尝试使其变得易于测试/可仿冒.考虑一下:

If you really want to go with a static Settings class I would at least try to make it test-friendly/fakeable. Consider this:

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

以及构建容器的位置:

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

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

这将允许在测试过程中与假货交换:

This would allow to swap out with fakes during test:

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

现在,您可以使用常规构造函数注入来实现AppSettings类(我认为只有一个).我还假设您确实要对每次对您的settings属性的调用进行解析,从而注入一个工厂委托,以便在需要时检索实例.如果不需要,您当然应该直接注入IConfigurationSettings服务.

Now the AppSettings class (which I assume there is only one of) you could do with regular constructor injection. I assume also that you really want to do a resolve on each call to your settings properties, thus injecting a factory delegate that retrieves an instance when needed. If this is not needed you should of course inject the IConfigurationSettings service directly.

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"];
        }
    }
}

这篇关于避免使用AutoFac 2服务定位器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆