微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

具有可触发初始化的C#Singleton模式

我需要一个单身人士:

>是懒惰加载
>是线程安全的
>在施工时加载一些值
>可以随时查询这些值
>初始化可能在查询开始之前的某个精确时间发生 – 所以我必须能够以某种方式从外部触发它.当然,多次触发应该只进行一次初始化.

我使用.NET 3.5.

我使用静态子类开始使用Jon Skeet的implementation(第5版):

public sealed class Singleton
{
    IEnumerable<string> Values {get; private set;}
    private Singleton()
    {
        Values = new[]{"quick","brown","fox"};
    }

    public static Singleton Instance { get { return nested.instance; } }

    private class nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

除了“从外部触发初始化”之外,几乎所有方框都会打勾.由于实际初始化发生在ctor内部,因此不会发生多次.

如何实现这一目标?

单例将使用如下:

public static void Main(){

    //do stuff,singleton should not yet be initialized.

    //the time comes to initialize the singleton,e.g. a database connection is available
    //this may be called 0 or more times,possibly on different threads

    Singleton.Initialize();
    Singleton.Initialize();
    Singleton.Initialize();

    //actual call to get retrieved values,should work
    var retrieveVals = Singleton.Instance.Values;

}

解决方法

好像你可以这样做:
public sealed class Singleton
{
    IEnumerable<string> Values {get; private set;}
    private Singleton(bool loadDefaults)
    {
        if (loadDefaults)
            Values = new[]{"quick","fox"};
        else
            Values = new[]{"another","set","of","values"};
    }

    public static Singleton Instance { get { return nested.instance; } }

    public static void Initialize() {
        nested.Initialize();
    }

    private class nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static nested()
        {
        }

        internal static readonly Singleton instance = new Singleton(true);
        private static object instanceLock = new object();
        private static bool isInitialized = false; 

        public static void Initialize() {
            lock(instanceLock) {
                if (!isInitialized) {
                    isInitialized = true;
                    instance = new Singleton(false);
                }
            }
        }

    }
}

或者创建一个将要更新的单个实例:

public sealed class Singleton
{
    IEnumerable<string> Values {get; private set;}
    private Singleton()
    {
        Values = new[]{"quick","fox"};
    }

    public static Singleton Instance { get { return nested.instance; } }

    private static object instanceLock = new object();
    private static bool isInitialized = false; 

    public static void Initialize() {
        lock(instanceLock) {
            if (!isInitialized) {
                isInitialized = true;
                Instance.Values = new[]{"another","values"};
            }
        }
    }

    private class nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

第三个变体基于您的不可变注释和删除嵌套类注释:

public sealed class Singleton
{
    IEnumerable<string> Values {get; private set;}
    private Singleton()
    {
        Values = new[]{"quick","fox"};
    }

    private static Singleton instance;
    private static object instanceLock = new object();

    public static Singleton Instance {
        get {
            Initialize();
            return instance;
        }
     }

    public static void Initialize() {
        if (instance == null) {
            lock(instanceLock) {
                if (instance == null)
                    instance = new Singleton();
            }
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐