使用 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<T>()
{
return _resolver.Resolve<T>();
}
}
从上一个问题,我找到了一种方法,通过使用 自动生成的工厂。继续沿着这条路走下去,我很好奇是否可以完全消除我的 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 个领域:
- AppSettings
- 日志记录
- 缓存
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.
Here is the scenario:
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>();
}
}
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
- Logging
- Caching
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我宁愿将
IAppSettings
注入到每个需要它的类中,只是为了让它们摆脱对Settings
的隐藏依赖。问题是,您真的需要将这种依赖关系散布到每个类中吗?如果您真的想使用静态
Settings
类,我至少会尝试使其测试友好/可伪造。考虑一下:以及在哪里构建容器:
这将允许在测试期间用假货进行交换:
现在您可以使用常规构造函数注入来执行 AppSettings 类(我假设只有一个)。我还假设您确实希望对设置属性的每次调用进行解析,从而注入一个工厂委托,在需要时检索实例。如果不需要,您当然应该直接注入
IConfigurationSettings
服务。I would rather inject
IAppSettings
into every class that needs it just to keep them clean from the hidden dependency onSettings
. Question is, do you really need to sprinkle that dependency into each and every class?If you really want to go with a static
Settings
class I would at least try to make it test-friendly/fakeable. Consider this:And where you build your container:
This would allow to swap out with fakes during test:
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 theIConfigurationSettings
service directly.