我有一个Singleton,它充当Web应用程序的上下文对象。这个Singleton跟随Jon Skeets非常出色Lazy Singleton model。
最终结果是一个Context.Current
对象,它作为许多函数的参考点。
我遇到的问题是这个对象的属性是一个名为Providers
的类。它为我提供了有关一系列云提供商的OAuth信息,如ClientId。
对于大多数提供商,ClientIds会根据您的端点进行更改,因此在每个提供商的构造函数中,我检查...您猜对了,Context.Current.DeploymentType
这是一个ENUM
,告诉我哪个环境我&# 39; m in。
在它实例化期间调用一个对象是非常糟糕的形式,我最终得到了一个:
ValueFactory attempted to access the Value property of this instance.
现在,我可能根本不在Context.Current.DeploymentType
的构造函数中引用Provider
,而只是执行ENUM
一遍又一遍地实例化所做的相同工作,但感觉低效的。
我可以单独创建ENUM
,然后再为Context.Current
创建,但这也感觉不对。
我目前的代码是:
public Providers AllProviders = Providers.Instance;
有没有办法说:
public Providers AllProviders {get; don't instantiate me until someone calls me}
答案 0 :(得分:1)
这在Singleton模式中实际上并不罕见。正在初始化的对象需要从单例中访问属性,该属性尚未初始化。通常,解决这个问题的方法是延迟初始化其他实例和属性以避免此问题。
在您的示例中,由于其声明,属性在对象构造期间初始化。为了避免在对象构造期间初始化它,您可以这样做:
public Providers AllProviders
{
get
{
if (this.allProviders == null) this.allProviders = Providers.Instance; // alternatively, do what Providers.Instance is actually doing
return this.allProviders;
}
}
如果我理解正确的话,看起来应该解决这个问题。通过进行此更改,在构造期间,属性未初始化,并且不调用Providers.Instance。只有在访问AllProviders时才会调用(然后缓存)。
当然,它不是线程安全的(除非Providers.Instance已经是线程安全的)并且您可能需要做一些工作才能使其成为线程安全的,这将通过您拥有的方法实现建议(即“在有人给我打电话之前不要实例化我”)。