如何初始化和/或注入单例或静态字典

时间:2017-03-22 17:57:53

标签: c# dependency-injection singleton

我需要一个将在启动时配置并且永远不会更改的字典。 要求:

  • 配置需要I / O(昂贵),所以我想确保这只发生一次。
  • 只有一个班级会使用它,所以我希望隐藏在程序的其他部分。
  • 我希望(如果可能的话)能够在单元测试中换掉字典以进行模拟。

有没有办法达到所有这些目标?

我考虑的选项

  1. 私有静态字典。这很简单,它可以确保单个实例,并使其隐藏。但我不知道如何模仿它。另外,不知道如何从配置文件中实例化它。
  2. Singleton继承自字典。确保单一实例化,可以从构造函数中的文件完成。我可以通过将其嵌套在客户端类中来隐藏。它添加了几行代码,但这是可以忍受的。但是我仍然无法弄清楚如何注入模拟器进行测试。
  3. 这是展示这两种方法的代码的简化版本:

        public class Foo
        {
            private NestedSingleton nestedSingleton = NestedSingleton.GetInstance;
            public string SomeItemFromStatic { get { return (staticDict[1]);  } }
            public string SomeItemFromSingleton { get { return (nestedSingleton[1]);  } }
    
            private static Dictionary<int, double> staticDict = new Dictionary<int, double>()
            { //Need to instantiate values from config file. But don't know how...
                    { 1, 1.345396 },
                    { 2, 29.34396 },
                    { 3, 17.34396 },
            };      
    
            class NestedSingleton : Dictionary<int, double>
            {
                private static readonly NestedSingleton _instance;
                static NestedSingleton() 
                {           
                    _instance = new NestedSingleton() //Actual code reads from config file here
                    {
                        { 1, 1.345396 },
                        { 2, 29.34396 },
                        { 3, 17.34396 },
                    };
                }
                private NestedSingleton() { } // Private ctor enforces Singleton pattern
                public static NestedSingleton GetInstance { get { return _instance; } }
            }
        }
    

    有没有办法满足所有规定的要求? (注意:此时我还没有引入DI框架。如果可能的话,我更喜欢不依赖于其中的答案。)

1 个答案:

答案 0 :(得分:1)

不是创建字典,而是创建字典&#34; loader&#34;抽象,将此抽象/接口的实例传递给被测试的类。

你可以模拟装载机,它将返回任何&#34;伪造的&#34;字典。

然后将loader实现为&#34; CachedLoader&#34;这将在本地保存加载的字典,并通过属性或方法为消费者返回实例。

加载程序的实现可以保持单例

public interface IConfiguration
{
    public IDictionary<int, int> Data { get; }
}

public class YourClass
{
    private readonly IConfiguration _configuration;

    public YourClass(IConfiguration configuration)
    {
        _configuration = configuration
    }

    public bool GetValue(int id)
    {
        return _configuration.Data[id];
    }
}

public class CachedConfiguartion : IConfiguartion
{
    public IDictionary<int, int> _cachedData;
    public IDictionary<int, int> Data { get { return _cachedCData; } }

    public CachedConfiguartion() {}
}

对于CachedConfiguartion,您可以使用专用方法加载字典,或者制作Data类型的Lazy<Dictionary<int, int>>并在首次使用时加载