C#に非デフォルトコンストラクターを備えたシングルトンを使用することは可能ですか?

StackOverflow https://stackoverflow.com/questions/885972

質問

プロジェクトの1つに通知フレームワークを実装しています。私はそれを非常に一般的にしたいので、ユーザーはいくつかの輸送層を使用することができます。そのため、彼は実際に1つの配信方法(WCFなど)または別のもの(ActiveMQなど)を使用することを気にする必要はありません。ユーザーがアクセスできるインターフェイスは、もちろん配信方法(WCFまたはActiveMQ)とは無関係です。それでも、2つのクラス(コンシューマーとプロデューサー)はシングルトンを実装するため、実際にデフォルトのコンストラクター(つまり、パラメーターなし)を使用します。私の問題は、1つのパラメーター、ユーザーが使用したい配信方法を持ちたいということです。しかし、私の知る限り、シングルトンはデフォルトのコンストラクターのみを使用していますか?パラメーターを備えたシングルトンを使用する点がないはずです。それで、ここでの私の選択肢は何ですか?シングルトンを作らない?配信方法を設定する方法を作成しますか?

ご助力ありがとうございます、

セバスチャン

役に立ちましたか?

解決

パラメーターをコンストラクターに渡すのではなく、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) 
}

他のヒント

spring.netのような依存関係インジェクションフレームワークがあります。シングルトンコンストラクターの構成ファイルでパラメーターを効果的に渡すことができます。

スプリングフレームワークの例にリンクします

Singletonに2つの異なる動作が必要な場合は、サブクラス化することをお勧めします。そうすれば、あなたが望むクラスの動作のシングルトンに電話することで、あなたが望む動作を得ることができます。

これは、依存関係噴射フレームワークで簡単に行うことができます。現在のプロジェクトには同様の構成要素があります mef. 。必要なのは、コンストラクターインジェクションオプションを使用し、そのアセンブリと要求された依存関係のアセンブリをカタログに追加することです。

別のオプションは、オプションを取得し、Singletonインスタンスを構築する何らかの初期化関数を作成することです。最初のアクセスで構築する代わりに、初期化の呼び出し中に構築できます。ここでのマイナス面は、使用する前にシングルトンを初期化する必要があることです(通常、プログラムの開始時、構成ファイルを使用して)。

同様の、しかしそれほどエラーが発生しないオプションは、SingletonがLazy Initializeを使用するだけで、「デフォルト」オプションを提供することです。発信者が静的プロパティを設定して、どのオプションを構築するかを変更できるようにするため、Singletonの構造の前に設定されている場合、別のデフォルトが得られます。ただし、これは混乱を招く可能性がありますが、繰り返しますが、シングルトンにアクセスする前にプロパティを設定する必要があるか、予期しない動作が得られるためです。

私は元の質問に答えるのが遅いことを知っていますが、私はこの問題を抱えていただけで、ここでそれを解決した方法があります。理想的ではないかもしれませんが、うまくいくようです。 Singletonインスタンスを使用しようとする前に呼び出さなければならないINITメソッドを作成しました。

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

Singletonインスタンス(プロパティGet、Set、Method Call)へのその他のアクセスは、オブジェクトが初期化されていないことを示す無効な操作例外をスローします。

これは私に必要なことを行うと思いますが、その方法が何をするかを誤解するリスクがないため、GetInstance(Params)よりも混乱していません。マイナス面は、コンピレーションタイムエラーを投げることはないということですが、初期化が行われない最初の実行は例外を投げかけるので、それは十分であるはずです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top