可以在C#中使用带有非默认构造函数的单例吗?

时间:2009-05-20 03:04:08

标签: c# singleton default-constructor

我正在为我的一个项目实施通知框架。由于我希望它非常通用,用户可以使用多个传输层,因此他并不需要关心使用一种传递方法(比如说WCF)或另一种传递方法(例如ActiveMQ)。 用户可以访问的界面当然与传递方法(WCF或ActiveMQ)无关。 尽管如此,这两个类(消费者和生产者)实现了单例,因此它们实际上使用默认构造函数(意思是没有参数)。 我的问题是,我想有一个参数,用户想要使用的交付方法。 但据我所知,单身人士只使用默认构造函数?这是正常的,因为没有必要使用带参数的单例。 那么,我的选择是什么?不要创建一个单身人士?创建一个设置交付方式的方法?

非常感谢你的帮助,

塞巴斯蒂安

4 个答案:

答案 0 :(得分:5)

你当然可以使用单例参数,除了不将参数传递给构造函数,而是将它传递给getInstance()方法。您的被覆盖的构造函数当然需要是私有的,才能实现真正的单例实现。我的例子是用Java编写的,但也适用于C#。

示例:

Singleton s = Singleton.getInstance(42);

在Singleton代码中:

private Singleton() {

}

private Singleton(int num) {
   //set num
}

public getInstance(int num) {
  //singleton code (calls the private non-default constructor if an object 
  //does not already exist) 
}

答案 1 :(得分:0)

有一些像Spring.Net这样的依赖注入框架可能对你有帮助。您可以在单例构造函数的配置文件中有效地传递参数。

Link to a Spring Framework example

我可能会建议,如果您的单身人员需要两种不同的行为,那么您可能想要进行子类化。这样,您可以通过调用所需类行为的单例来获得所需的行为。

答案 2 :(得分:0)

您可以使用依赖注入框架轻松完成此操作。我使用MEF在当前项目中有类似的构造。所需要的只是使用构造函数注入选项,并将该程序集和请求的依赖项程序集添加到目录中,并将其正确连接。

另一种选择是使用某种形式的初始化函数来获取你的选项,并构造单例实例。您可以在初始化调用期间构建它,而不是在第一次访问时构造它。这里的缺点是你需要确保在使用它之前初始化你的单例(通常在程序启动时,使用配置文件)。

类似但不易出错的选项是让单例延迟初始化,并给它一个“默认”选项。允许调用者设置静态属性以改变构造哪个选项,因此如果在单例构造之前设置它,则会得到不同的默认值。但是,这可能令人困惑,因为再次,您需要确保在访问单例之前设置属性,否则您将获得意外行为。

答案 3 :(得分:0)

我知道回答原始问题已经很晚了,但我刚遇到这个问题,这就是我如何解决它的问题。可能不理想,但似乎有效。 我创建了一个必须在尝试使用单例实例之前调用的Init方法。

public void Init(/*parameters*/)
{
        if (_isInitialized)
        {
            throw new InvalidOperationException("Component is already initialized!");
        }
        //do your work here
}

对单例实例的任何其他访问(属性get,set,方法调用)都将抛出一个无效的操作异常,告知该对象未被初始化。

我认为这样做我需要的,比GetInstance(params)更容易混淆,因为没有误解方法的作用的风险。缺点是它不会抛出编译时错误,但没有初始化完成的第一次运行会引发异常,所以它应该足够好。