带有接受参数的构造函数的 C# Singleton
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1122900/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# Singleton with constructor that accepts parameters
提问by
I want to create a static class or singleton class that accepts a reference to another object in its constructor. Static classes are out, but I figured I could create a singleton that accepts parameters in its constructor. So far I haven't had any luck figuring out or googling the syntax. Is this possible? if so, how do I do it?
我想创建一个静态类或单例类,它在其构造函数中接受对另一个对象的引用。静态类已经过时了,但我想我可以创建一个在其构造函数中接受参数的单例。到目前为止,我还没有找到或谷歌搜索语法的运气。这可能吗?如果是这样,我该怎么做?
Sorry for no example in the initial post, I wrote it in a rush. I have the feeling that my answer is already in the replies, but here's some clarification of what I want to do:
抱歉,在最初的帖子中没有示例,我匆忙写了。我感觉我的答案已经在回复中了,但这里有一些我想要做的澄清:
I want to create a single instance of a specific type (said Singleton), but that single instance of the type needs to hold a reference to a different object.
我想创建特定类型的单个实例(如 Singleton),但该类型的单个实例需要保存对不同对象的引用。
For example, I might want to create a Singleton "Status" class, which owns a StringBuilder object and a Draw() method that can be called to write said StringBuilder to the screen. The Draw() method needs to know about my GraphcisDevice in order to draw. So what I want to do it this:
例如,我可能想要创建一个单例“状态”类,它拥有一个 StringBuilder 对象和一个 Draw() 方法,可以调用该方法将所述 StringBuilder 写入屏幕。Draw() 方法需要知道我的 GraphcisDevice 才能进行绘制。所以我想这样做:
public class Status
{
private static Status _instance;
private StringBuilder _messages;
private GraphicsDevice _gDevice;
private Status(string message, GraphicsDevice device)
{
_messages.Append(message);
_gDevice = device;
}
// The following isn't thread-safe
// This constructor part is what I'm trying to figure out
public static Status Instance // (GraphicsDevice device)
{
get
{
if (_instance == null)
{
_instance = new Status("Test Message!", device);
}
return _instance;
}
}
public void UpdateMessage
...
public void Draw()
{
// Draw my status to the screen, using _gDevice and _messages
}
}
All over the code, I retrieve my Status Singleton and call its UpdateMessage() method.
在整个代码中,我检索我的 Status Singleton 并调用它的 UpdateMessage() 方法。
private Status _status = Status.Instance; // + pass reference to GraphicsDevice
_status.UpdateMessage("Foo!");
Then, in my main class I also retrieve the singleton, and draw it:
然后,在我的主类中,我还检索了单身人士,并绘制了它:
_status.Draw();
Yes, this means that wherever I retrieve the singleton, I need to do so by passing in the reference to the GraphicsDevice, in case it's the first time I instantiate the Singleton. And I could/would use different means to retrieve something as fundamental as the GraphicsDevice in my Singleton class, for example register a service elsewhere and get that service in the Status class. This example got pretty contrived - I'm trying to figure out if somethinglike this pattern is possible in the first place.
是的,这意味着无论我在哪里检索单例,我都需要通过传递对 GraphicsDevice 的引用来这样做,以防这是我第一次实例化单例。我可以/将使用不同的方法来检索与我的 Singleton 类中的 GraphicsDevice 一样基本的东西,例如在别处注册一个服务并在 Status 类中获取该服务。这个例子得到相当做作-我试图找出如果事情像这个模式首先是可能的。
回答by Robert Harvey
What you are describing is a Generic Singleton. It looks like this:
您所描述的是通用单例。它看起来像这样:
public class SingletonProvider <T> where T:new()
{
SingletonProvider() {}
public static T Instance
{
get { return SingletonCreator.instance; }
}
class SingletonCreator
{
static SingletonCreator() { }
internal static readonly T instance = new T();
}
}
回答by Andrew Hare
This is generally considered a bad idea because if you are going to accept either an object reference or a type argument that you plan on wrapping in a singleton-like wrapper you cannot guarantee that you hold the only instance of that type in the AppDomain.
这通常被认为是一个坏主意,因为如果您打算接受一个对象引用或一个您计划包装在类似单例的包装器中的类型参数,则不能保证您在 AppDomain 中持有该类型的唯一实例。
The whole point of the singleton pattern is to control a single instance of a type so that only one instance of that type can exist. If you allow an instance to be passed in or if you make a generic singleton provider you cannot guarantee that your instance is the onlyinstance.
单例模式的全部意义在于控制一种类型的单个实例,以便只能存在该类型的一个实例。如果您允许传入一个实例,或者您创建了一个通用的单例提供程序,则您不能保证您的实例是唯一的实例。
Let's say that I had a SingletonFactory<T>
that would allow me to create a singleton around any type that I pass to the factory. That would be quite handy and would allow me to do something like this:
假设我有一个SingletonFactory<T>
允许我围绕我传递给工厂的任何类型创建单例。这将非常方便,并且可以让我做这样的事情:
SingletonFactory<Foo>.Instance;
But what stops me from also doing this:
但是是什么阻止了我也这样做:
Foo foo = new Foo();
Oops, it looks like Foo
isn't a singleton anymore as I can create as many instances of it as I wish. In order for the singleton pattern to work you need to be able to completely control the type whose instances you need to restrict. This is why you ought not to use anything like my SingletonFactory<T>
.
糟糕,它看起来Foo
不再是单例了,因为我可以根据需要创建尽可能多的实例。为了使单例模式起作用,您需要能够完全控制需要限制其实例的类型。这就是为什么你不应该使用像 my SingletonFactory<T>
.
Note:The same goes for a non-generic singleton that accepts an object instance. I am sure that you can extrapolate from my previous example many similar reasons why a singleton wrapper that accepts and object reference would also be a bad idea.
注意:同样适用于接受对象实例的非泛型单例。我相信您可以从我之前的示例中推断出许多类似的原因,为什么接受和对象引用的单例包装也是一个坏主意。
回答by Tim Sylvester
What you're specifically asking for looks like this, I think:
你特别要求的看起来像这样,我认为:
public sealed class Singleton {
static Singleton instance = null;
static readonly object padlock = new Object();
Object o;
Singleton(Object _o) {
o = _o;
}
public static Singleton Instance(Object _o) {
lock (padlock) {
if (instance == null) {
instance = new Singleton(_o);
}
return instance;
}
}
}
Singleton s = Singleton.Instance(new Object());
I suspect that the generic version already posted is what you really want, though.
不过,我怀疑已经发布的通用版本是您真正想要的。
回答by Alaor
You need a private constructor and then a getInstance method, this method is who should receive the param, the constructor must be private and it can have params also, but getInstance should pass it, no you. Btw, what you're doing? Some real example could help.
你需要一个私有构造函数,然后是一个 getInstance 方法,这个方法是谁应该接收参数,构造函数必须是私有的,它也可以有参数,但是 getInstance 应该传递它,不是你。顺便说一句,你在做什么?一些真实的例子可能会有所帮助。
回答by Chansik Im
One thing you can do may be sticking to the singleton sample you found and just exposing a property (setter, if needed, add getter as well) and use it like
MySingleton.Instance.MyReference = new MyObject();
您可以做的一件事可能是坚持您找到的单例示例并仅公开一个属性(setter,如果需要,还可以添加 getter)并像这样使用它
MySingleton.Instance.MyReference = new MyObject();
If you have to restrict the usage of your singleton object, for example, any operations on the singleton object before the reference is set need to be illegal, you can have a private boolean flag, for example, hasBeenIntialized and MyReference setter will set the flag internally. All other methods will check the flag at the beginning of the execution and throw an exception if any method is called if hasBeenInitialized is false.
如果你必须限制你的单例对象的使用,例如在设置引用之前对单例对象的任何操作都需要是非法的,你可以有一个私有的布尔标志,例如 hasBeenIntialized 和 MyReference setter 将设置该标志内部。所有其他方法将在执行开始时检查标志,并在 hasBeenInitialized 为 false 时调用任何方法时抛出异常。
If you need to have a readonly behavior, you may throw an exception in MyReference setter if anyone wants to assign a different object while hasBeenInitialized is set to true.
如果您需要具有只读行为,并且当 hasBeenInitialized 设置为 true 时,如果有人想要分配不同的对象,您可能会在 MyReference setter 中抛出异常。