避免使用AutoFac 2服务定位器 [英] Avoiding Service Locator with 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屋!