C#Singleton,带有接受参数的构造函数

时间:2009-07-14 00:36:46

标签: c# constructor singleton

我想创建一个静态类或单例类,它接受对其构造函数中另一个对象的引用。静态类已经出来了,但我想我可以创建一个在其构造函数中接受参数的单例。到目前为止,我没有任何运气搞清楚或谷歌搜索语法。这可能吗?如果是的话,我该怎么做?

很抱歉在最初的帖子中没有任何例子,我急忙写下来。我觉得我的回答已经在回复中了,但是这里有一些关于我想要做的事情的澄清:

我想创建一个特定类型的单个实例(表示Singleton),但该类型的单个实例需要保存对不同对象的引用。

例如,我可能想创建一个Singleton“Status”类,它拥有一个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
    }
}  

在整个代码中,我检索Status Singleton并调用其UpdateMessage()方法。

private Status _status = Status.Instance; // + pass reference to GraphicsDevice
_status.UpdateMessage("Foo!");

然后,在我的主要课程中,我也检索单身人士,并绘制它:

_status.Draw();

是的,这意味着无论我在哪里检索单例,我都需要通过传入对GraphicsDevice的引用来实现,以防它是第一次实例化Singleton。我可以/将使用不同的方法来检索像我的Singleton类中的GraphicsDevice一样基本的东西,例如在其他地方注册服务并在Status类中获取该服务。这个例子非常有用 - 我试图弄清楚某些这样的模式是否可行。

5 个答案:

答案 0 :(得分:17)

这通常被认为是一个坏主意,因为如果你要接受一个对象引用或你计划包装在类似单身的包装器中的类型参数,你不能保证你在这个包含中保留该类型的唯一实例。应用程序域。

单例模式的重点是控制一个类型的单个实例,以便只存在该类型的一个实例。如果允许传入实例,或者如果您创建通用单例提供程序,则无法保证您的实例是 only 实例。

假设我有一个SingletonFactory<T>允许我创建一个围绕我传递给工厂的任何类型的单例。这将非常方便,并允许我做这样的事情:

SingletonFactory<Foo>.Instance;

但是什么阻止了我这样做:

Foo foo = new Foo();

糟糕,看起来Foo不再是单身,因为我可以根据自己的意愿创建尽可能多的实例。为了使单例模式起作用,您需要能够完全控制需要限制其实例的类型。这就是为什么你不应该使用像SingletonFactory<T>那样的东西。

注意: 对于接受对象实例的非通用单例也是如此。我相信你可以从我之前的例子中推断出许多类似的原因,为什么接受和对象引用的单例包装器也是一个坏主意。

答案 1 :(得分:2)

您所描述的是Generic Singleton。它看起来像这样:

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();
    }
}

http://www.codeproject.com/KB/cs/genericsingleton.aspx

答案 2 :(得分:2)

我认为你明确要求的是这样的,我想:

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());

我怀疑已发布的通用版本是你真正想要的。

答案 3 :(得分:1)

你需要一个私有构造函数然后一个getInstance方法,这个方法是谁应该接收param,构造函数必须是私有的,它也可以有params,但是getInstance应该传递它,不是你。顺便问一下,你在做什么?一些真实的例子可以提供帮助。

答案 4 :(得分:0)

你可以做的一件事可能是坚持你找到的单例样本,只是暴露一个属性(如果需要的话,设置者,添加getter)并像使用它一样  MySingleton.Instance.MyReference = new MyObject();

如果必须限制单例对象的使用,例如,在设置引用之前对单例对象的任何操作都需要是非法的,则可以使用私有布尔标志,例如hasBeenIntialized和MyReference setter将在内部设置标志。所有其他方法将在执行开始时检查标志,如果hasBeenInitialized为false,则调用任何方法时抛出异常。

如果您需要具有只读行为,则可以在MyReference setter中抛出异常,如果有人想要在hasBeenInitialized设置为true时分配不同的对象。