3

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

非常感谢您的帮助,

塞巴斯蒂安

4

4 回答 4

5

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

例子:

Singleton s = Singleton.getInstance(42);

在单例代码中:

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) 
}
于 2009-05-20T03:18:38.987 回答
0

有一些依赖注入框架,如 Spring.Net,可能会对您有所帮助。您可以有效地在配置文件中为单例构造函数传递参数。

链接到 Spring 框架示例

我是否可以建议,如果您的单例需要两种不同的行为,您可能想要子类化。这样你就可以通过调用你想要的类行为的单例来获得你想要的行为。

于 2009-05-20T03:21:28.167 回答
0

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

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

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

于 2009-05-20T04:17:34.687 回答
0

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

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

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

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

于 2012-02-02T13:51:54.720 回答