web-dev-qa-db-ja.com

パラメータを受け入れるコンストラクタを備えたC#シングルトン

コンストラクターで別のオブジェクトへの参照を受け入れる静的クラスまたはシングルトンクラスを作成したいと思います。静的クラスは出ていますが、コンストラクターでパラメーターを受け入れるシングルトンを作成できると思いました。これまでのところ、構文を理解したりグーグルで調べたりすることはできませんでした。これは可能ですか?もしそうなら、どうすればいいですか?

最初の投稿に例がないので申し訳ありませんが、私はそれをラッシュで書きました。私の答えはすでに返信に含まれているように感じますが、これが私がやりたいことのいくつかの明確化です:

特定のタイプ(シングルトンと呼ばれる)の単一インスタンスを作成したいのですが、そのタイプの単一インスタンスは別のオブジェクトへの参照を保持する必要があります。

たとえば、StringBuilderオブジェクトと、そのStringBuilderを画面に書き込むために呼び出すことができるDraw()メソッドを所有するシングルトン「Status」クラスを作成したい場合があります。 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への参照を渡すことによって取得する必要があることを意味します。また、別の方法を使用して、シングルトンクラスのGraphicsDeviceと同じくらい基本的なものを取得できます。たとえば、他の場所でサービスを登録し、そのサービスをStatusクラスで取得します。この例はかなり不自然になりました-そもそもこのパターンが可能かどうかを理解しようとしています何か

22
Drakestar

シングルトンのようなラッパーでラップする予定のオブジェクト参照または型引数のいずれかを受け入れる場合、AppDomainでその型の唯一のインスタンスを保持することを保証できないため、これは一般に悪い考えと見なされます。

シングルトンパターンの要点は、タイプの単一インスタンスを制御して、そのタイプのインスタンスが1つだけ存在できるようにすることです。インスタンスの受け渡しを許可する場合、または汎用シングルトンプロバイダーを作成する場合、インスタンスがonlyインスタンスであることを保証することはできません。

工場に渡すすべてのタイプの周りにシングルトンを作成できるSingletonFactory<T>があったとしましょう。これは非常に便利で、次のようなことができます。

SingletonFactory<Foo>.Instance;

しかし、私がこれを行うのを妨げるものは何ですか:

Foo foo = new Foo();

Fooは、必要な数のインスタンスを作成できるため、シングルトンではなくなったようです。シングルトンパターンが機能するためには、インスタンスを制限する必要があるタイプを完全に制御できる必要があります。これが、私のSingletonFactory<T>のようなものを使用すべきではない理由です。

注:オブジェクトインスタンスを受け入れる非ジェネリックシングルトンについても同じことが言えます。前の例から、オブジェクト参照を受け入れるシングルトンラッパーも悪い考えである多くの同様の理由を推定できると確信しています。

17
Andrew Hare

あなたが説明しているのはジェネリックシングルトンです。次のようになります。

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
Robert Harvey

あなたが特に求めているものは次のようになります、私は思います:

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

ただし、すでに投稿されている汎用バージョンが本当に必要なものだと思います。

2
Tim Sylvester

プライベートコンストラクターとgetInstanceメソッドが必要です。このメソッドは、パラメーターを受け取る必要があります。コンストラクターはプライベートである必要があり、パラメーターも含めることができますが、getInstanceはそれを渡す必要があります。ところで、あなたは何をしているのですか?いくつかの実際の例が役立つ可能性があります。

1
Alaor

できることの1つは、見つけたシングルトンサンプルに固執し、プロパティを公開して(必要に応じて、ゲッターも追加する)、MySingleton.Instance.MyReference = new MyObject();のように使用することです。

シングルトンオブジェクトの使用を制限する必要がある場合、たとえば、参照が設定される前のシングルトンオブジェクトに対する操作が違法である必要がある場合は、プライベートブールフラグを設定できます。たとえば、hasBeenIntializedとMyReferenceセッターがフラグを設定します内部的に。他のすべてのメソッドは、実行の開始時にフラグをチェックし、hasBeenInitializedがfalseの場合にメソッドが呼び出されると、例外をスローします。

読み取り専用の動作が必要な場合、hasBeenInitializedがtrueに設定されているときに誰かが別のオブジェクトを割り当てたい場合は、MyReferenceセッターで例外をスローできます。

0
Chansik Im