代码之家  ›  专栏  ›  技术社区  ›  Page

使用Autopac 2避免服务定位器

  •  5
  • Page  · 技术社区  · 16 年前

    我正在构建一个应用程序,它使用autopac2进行DI。我一直在 reading 应该避免使用静态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>();
        }
    }
    

    从答案到 previous question 我找到了一种方法,通过使用 Auto-generated Factories . 继续沿着这条路走,我很好奇我是否能完全消除我的iocHelper。

    以下是场景:

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

    设置.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个方面:

    • 应用程序设置
    • 登录中
    • 缓存
    1 回复  |  直到 16 年前
        1
  •  4
  •   Peter Lillevold Rene    16 年前

    我宁愿注射 IAppSettings 到每个需要它的类中,只是为了让它们远离对 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"];
            }
        }
    }
    
    推荐文章