C#具有可触发初始化的单例模式我需要一个单例:我使用.NET3.5。我从使用静态子类化的JonSkeet的实现(版本5)开始:publicsealedclassSingleton{IEnumerableValues{get;privateset;}privateSingleton(){Values=new[]{"quick","brown","fox"};}publicstaticSingletonInstance{get{returnNested.instance;}}privateclassNested{//显式静态构造函数告诉C#编译器//不要将类型标记为beforefieldinitstaticNested(){}internalstaticreadonlySingletoninstance=newSingleton();}}除了“从外部触发初始化”之外,几乎所有的方框都被勾选了。由于实际的初始化发生在ctor内部,因此不会发生多次。如何实现这一目标?//初始化单例的时候到了,例如数据库连接可用//这可能被调用0次或多次,可能在不同的线程上Singleton.Initialize();单例初始化();单例初始化();//获取检索值的实际调用,应该有效varretrieveVals=Singleton.Instance.Values;}好象你可以这样做:publicsealedclassSingleton{IEnumerableValues{get;私有集;}privateSingleton(boolloadDefaults){if(loadDefaults)Values=new[]{"quick","brown","fox"};elseValues=new[]{“另一个”,“集合”,“of”,“值”};}publicstaticSingletonInstance{get{returnNested.instance;}}publicstaticvoidInitialize(){Nested.Initialize();}privateclassNested{//显式静态构造函数告诉C#编译器//不要将类型标记为beforefieldinitstaticNested(){}internalstaticreadonlySingletoninstance=newSingleton(true);私有静态对象instanceLock=newobject();privatestaticboolisInitialized=false;publicstaticvoidInitialize(){lock(instanceLock){if(!isInitialized){isInitialized=true;instance=newSingleton(false);}}}}}或者创建者将要更新的单个实例:publicsealedclassSingleton{IEnumerableValues{get;私有集;}privateSingleton(){Values=new[]{"quick","brown","fox"};}publicstaticSingletonInstance{get{returnNested.instance;}}私有静态对象instanceLock=newobject();privatestaticboolisInitialized=false;publicstaticvoidInitialize(){lock(instanceLock){if(!isInitialized){isInitialized=true;Instance.Values=new[]{"另一个","集合","的","值"};}}}privateclassNested{//显式静态构造函数告诉C#编译器//不要将类型标记为beforefieldinitstaticNested(){}internalstaticreadonlySingletoninstance=newSingleton();}}第三个变量到您的不可变注释并删除嵌套类注释:publicsealedclassSingleton{IEnumerableValues{get;privateset;}privateSingleton(){Values=new[]{"quick","brown","fox"};私有静态单例实例;私有静态对象instanceLock=newobject();publicstaticSingletonInstance{get{Initialize();返回实例;}}publicstaticvoidInitialize(){if(instance==null){lock(instanceLock){if(instance==null)instance=newSingleton();}}}}可以设置一个可以在外部触发的Initialize方法,如果后面需要初始化,但是如果每次触发的值都不一样,那么就不能是静态的,违反了Singleton模式根据对于你的例子,它没有变量,我假设你只是在初始化发生时延迟(例程而不是构造函数),但你的问题表明你想要不同的值,但如果多个初始化一起发生它只初始化一次,所以我有点对此感到困惑。我不确定您是否只需要Singleton实现,但是如果没有关于Initialize()是否每次都运行相同的代码或者是否具有某种类型变量性质的信息,就无法完全回答这个问题。您可以使用双重检查锁定模式。只需要在您的单例类中添加以下代码:publicsealedclassSingleton{.....................privatestaticobjectlocker=newobject();私人静态布尔初始化=假;publicstaticvoidInitialize(){if(!initialized){lock(locker){if(!initialized){//在这里写初始化逻辑initialized=true;}}}}...................................}你可以做这样的事情publicsealedclassSingleton{IEnumerableValues{get;放;}privateSingleton(){Console.WriteLine("--PrivateSingletonconstructor");Values=new[]{"quick","brown","fox"};}publicstaticSingletonInstance{get{Console.WriteLine("-SingletonInstance");返回嵌套实例;}}publicstaticvoidInitialize(){Console.WriteLine("-SingletonInitialize");嵌套初始化();}内部类嵌套{私有静态对象syncRoot=newobject();//显式静态构造函数告诉C#编译器//不要将类型标记为beforefieldinitstaticNested(){Console.WriteLine("--静态嵌套构造函数");}internalstaticreadonlySingletoninstance=newSingleton();internalstaticvoidInitialize(){lock(syncRoot){Console.WriteLine("--Locked");Console.WriteLine("---NestedInitialize");Console.WriteLine("--Unlocked");}}}}使用方法classProgram{staticvoidMain(string[]args){vari=Singleton.Instance;i=Singleton.Instance;Console.WriteLine("-----");Singleton.Initialize();Singleton.Initialize();Singleton.Initialize();Console.Read();}}哪个输出-SingletonInstance--PrivateSingletonconstructor--StaticNestedconstructor-单例实例-----单例初始化--锁定---嵌套初始化--解锁-单例初始化--锁定---嵌套初始化--解锁-单例初始化--锁定---嵌套初始化--解锁publicclassSingletonwhereT:class,new(){privatestaticTinstance;publicstaticTInstance{get{if(instance==null){thrownewException("单例使用前需要初始化");}返回实例;}}publicstaticvoidInitialise(ActioninitializationAction){lock(typeof(Singleton)){if(instance!=null){return;}实例=新T();初始化动作(实例);我的第一个想法是使用分配给单例实例的一次性变量,这将(可能?)触发初始化staticMain(){varunused=Singleton.Instance;//这应该初始化单例,除非编译器优化它。//我想知道编译器是否足够聪明,可以看到这个调用有副作用。varvals=Singleton.Instance.Values;......但我试图避免在编程中使用副作用,所以让我们的意图更清楚publicclassSingleton{publicstaticvoidInitialize(){//这访问触发私有Singleton()ctor的内部类的静态字段。实例._Initialize();}privatevoid_Initialize(){//什么都不做}[其余如前]}所以用法是:staticMain(){//仍然想知道编译器是否可以优化这个调用Singleton.Initialize();varvals=Singleton.Instance.Values;}顺便说一句,这也有效:staticMain(){varvals=Singleton.Instance.Values;撇开编译器优化不谈,我认为这涉及到所有方面。以上就是C#学习教程:可触发初始化的C#单例模式分享的全部内容。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
