这个问题略有不同:Possible to use a singleton with a non-default constructor in C#?
我有一个为其构造函数提取参数的类。我想制作这个单例,以便在初始化单例时获取参数,因此在每次检索实例时都不需要传递参数。
我的解决方案(这不是优雅的)是有一个CreateInstance()
静态方法,它接受参数并构造单例实例。然后,我将有另一个静态方法GetInstance()
,它将无参数获取单例实例。在代码中,我需要在调用GetInstance之前确保逻辑调用CreateInstance
。但是,我无法在编译时强制执行此操作。但是,如果在GetInstance
之前调用异常,我可以在运行时检查异常{/ 1}}。
无论如何,我可以通过编译时执行来实现这种行为吗?或者至少,是否有更好的方法来做同样的事情?
答案 0 :(得分:5)
在编译时无法做到这一点,因为这就像询问编译器“你能证明在执行代码Y之前,在存在多个线程的情况下代码X永远不会被执行吗?”。它无法完成。
至于你的设计的运行时行为,我认为这是一如既往的好。
通过在单例类中公开Func<SingletonType>
属性,可以使其稍微好一些。当有人要求单例实例并且尚未创建实例时,您的类将调用此“工厂方法”来构造单例。如果工厂方法是null
,那么您可以使用一些默认参数抛出异常或(如果适用)构造。
这样做基本上推迟了单身人士的构建,直到第一次实际需要它为止,所以一些改进。但基本原则是一样的。
<强>更新强>
正如LukeH
所指出的,这几乎是Lazy<T>
所做的(仅限.NET 4)。如果可能的话,使用那个,而不是自己编写。
答案 1 :(得分:1)
在经典的单身人士中,真正的魔法发生在static readonly
中,它会在使用后立即创建实例:
public class MySingleton
{
private static readonly _instance = new MySingleton();
private MySingleton() {}
public static MySingleton Instance
{
get
{
return _instance;
}
}
}
如果你有要传递给构造函数的参数,你必须自己实现锁定(注意if
的双lock
个问题:
public class MySingletonWithConstructor
{
private static _instance;
private static object _lock = new Object();
private MySingletonWithConstructor(string myArg)
{
// ... do whatever necessary
}
public static MySingletonWithConstructor Instance
{
get
{
if(_instance==null)
{
lock(_lock)
{
if(_instance==null) // double if to prevent race condition
{
_instance = new MySingletonWithConstructor("Something");
}
}
}
return _instance;
}
}
}
答案 2 :(得分:0)
如果单例对象不存在,您可以GetInstance()
调用CreateInstance()
方法。
答案 3 :(得分:0)
我会这样做。您可能需要添加锁或其他内容以确保:
public class ClassA {
private static ClassA instance;
private int param;
private ClassA(int param) {
this.param = param;
}
public static ClassA getInstance() {
if (instance == null) {
throw new CustomException("Not yet initialised");
} else {
return instance;
}
}
public static void createInstance(int param) {
if (instance == null) {
instance = new ClassA(param);
}
}
}
答案 4 :(得分:0)
在你的GetInstance()
方法中,如果你的值为null,为什么不调用CreateInstance,那么你就是懒惰的初始化..
答案 5 :(得分:0)
使用CreateInstance()作为Lazy<T>
的加载器并让GetInstance返回Lazy.Value(您可能希望创建一个静态只读字段,设置为= thelazy.Value以确保单个条目进入的CreateInstance())