C# でシングルトン パターンを実装するにはどうすればよいですか? プロジェクトのあらゆる場所で定数といくつかの基本的な関数を使用するので、その中に定数といくつかの基本的な関数を入れたいと思います。それらを「グローバル」にしたいので、作成するすべてのオブジェクトを手動でバインドする必要はありません。
16 に答える
いくつかのグローバル値を格納するだけで、状態を必要としないメソッドがいくつかある場合、シングルトンは必要ありません。クラスとそのプロパティ/メソッドを静的にするだけです。
public static class GlobalSomething
{
public static int NumberOfSomething { get; set; }
public static string MangleString( string someValue )
{
}
}
シングルトンは、状態を持つ通常のクラスがある場合に最も役立ちますが、そのうちの 1 つだけが必要です。他の人が提供したリンクは、Singleton パターンを調べるのに役立つはずです。
Singleton != Global
. キーワードを探しているようですstatic
。
シングルトンの実装を本当に単純化できます。これが私が使用するものです。
internal FooService() { }
static FooService() { }
private static readonly FooService _instance = new FooService();
public static FooService Instance
{
get { return _instance; }
}
シングルトンは、次の両方の条件が真である場合にのみ意味があります。
- オブジェクトはグローバルでなければなりません
- オブジェクトの単一のインスタンスのみが存在する必要があります
#2は、オブジェクトに単一のインスタンスのみを持たせたいという意味ではないことに注意してください-その場合は、一度だけインスタンス化するだけです-必要があることを意味します(これが真実ではないのは危険です)単一のインスタンスになるだけです。
グローバルが必要な場合は、いくつかの(非サインルトン)オブジェクトのグローバルインスタンスを作成するだけです(または静的にするなど)。インスタンスが 1 つだけ必要な場合も、static が役に立ちます。また、オブジェクトを 1 つだけインスタンス化するだけです。
それはとにかく私の意見です。
うーん、これは少し複雑に思えます。
シングルトンを取得するために依存性注入フレームワークが必要なのはなぜですか? 一部のエンタープライズ アプリでは IOC コンテナーを使用しても問題ありませんが (もちろん、使いすぎない限り)、ああ、そのパターンの実装について知りたいだけです。
常に積極的にインスタンス化してから、静的を返すメソッドを提供しないのはなぜですか。上記のコードのほとんどはその後消えます。C2 の古い格言に従ってください - DoTheSimplestThingThatCouldPossiblyWork...
疎結合設計が必要な場合、静的シングルトンはほぼアンチ パターンです。可能であれば避けてください。これが非常に単純なシステムでない限り、 http: //ninject.org/やhttp://code.google.com/pなど、利用可能な多くの依存性注入フレームワークのいずれかを確認することをお勧めします。 /autofac/ .
autofac でシングルトンとして構成されたタイプを登録/使用するには、次のようにします。
var builder = new ContainerBuilder()
builder.Register(typeof(Dependency)).SingletonScoped()
builder.Register(c => new RequiresDependency(c.Resolve<Dependency>()))
var container = builder.Build();
var configured = container.Resolve<RequiresDependency>();
ちなみに、受け入れられた答えはひどい解決策です。少なくとも、実際にパターンを実装したチャップを確認してください。
MSDN で入手できるシングルトン デザイン パターンの探索という記事を読むことをお勧めします。パターンの実装を簡単にするフレームワークの機能について詳しく説明します。
余談ですが、関連する SO に関する Singletons の読み物をチェックアウトします。
他の場所で説明されているシングルトン パターンを使用する必要があるかどうかの問題を無視して、次のようなシングルトンを実装します。
/// <summary>
/// Thread-safe singleton implementation
/// </summary>
public sealed class MySingleton {
private static volatile MySingleton instance = null;
private static object syncRoot = new object();
/// <summary>
/// The instance of the singleton
/// safe for multithreading
/// </summary>
public static MySingleton Instance {
get {
// only create a new instance if one doesn't already exist.
if (instance == null) {
// use this lock to ensure that only one thread can access
// this block of code at once.
lock (syncRoot) {
if (instance == null) {
instance = new MySingleton();
}
}
}
// return instance where it was just created or already existed.
return instance;
}
}
/// <summary>
/// This constructor must be kept private
/// only access the singleton through the static Instance property
/// </summary>
private MySingleton() {
}
}
public class Globals
{
private string setting1;
private string setting2;
#region Singleton Pattern Implementation
private class SingletonCreator
{
internal static readonly Globals uniqueInstance = new Globals();
static SingletonCreator()
{
}
}
/// <summary>Private Constructor for Singleton Pattern Implementaion</summary>
/// <remarks>can be used for initializing member variables</remarks>
private Globals()
{
}
/// <summary>Returns a reference to the unique instance of Globals class</summary>
/// <remarks>used for getting a reference of Globals class</remarks>
public static Globals GetInstance
{
get { return SingletonCreator.uniqueInstance; }
}
#endregion
public string Setting1
{
get { return this.setting1; }
set { this.setting1 = value; }
}
public string Setting2
{
get { return this.setting2; }
set { this.setting2 = value; }
}
public static int Constant1
{
get { reutrn 100; }
}
public static int Constat2
{
get { return 200; }
}
public static DateTime SqlMinDate
{
get { return new DateTime(1900, 1, 1, 0, 0, 0); }
}
}
私はこのパターンが好きですが、誰かが非シングルトン インスタンスを作成することを妨げません。チームの開発者に正しい方法論を使用するように教育する方が良い場合があります。ナックルヘッドがコードを間違った方法で使用するのを防ぐために英雄的な長さまで行くよりも.
public class GenericSingleton<T> where T : new()
{
private static T ms_StaticInstance = new T();
public T Build()
{
return ms_StaticInstance;
}
}
...
GenericSingleton<SimpleType> builder1 = new GenericSingleton<SimpleType>();
SimpleType simple = builder1.Build();
Build() が呼び出されるまで静的コンストラクターが呼び出されないため、これにより単一のインスタンス (正しい方法でインスタンス化されたもの) が得られ、事実上遅延になります。
あなたが説明しているのは、シングルトンではなく、単なる静的関数と定数です。シングルトン デザイン パターン (必要になることはほとんどありません) は、インスタンス化されるクラスを記述しますが、最初の使用時に一度だけ自動的に作成されます。
遅延初期化とチェックを組み合わせて、複数のインスタンス化を防ぎます。これは、ハードウェア デバイスのラッパーなど、物理的に特異な概念をラップするクラスにのみ役立ちます。
静的定数と関数はまさにそれです: インスタンスをまったく必要としないコードです。
「このクラスのインスタンスが複数ある場合、このクラスは壊れますか?」と自問してください。答えが「いいえ」の場合、シングルトンは必要ありません。
うーん...関連する関数を持つ定数はほとんどありません...それは列挙型を介してよりよく達成されませんか? メソッドを使用してJavaでカスタム列挙型を作成できることは知っていますが、C#でも同じことが達成できるはずです。直接サポートされていない場合は、プライベートコンストラクターを使用した単純なクラスシングルトンで実行できます。
定数が意味的に関連している場合は、列挙型 (または同等の概念) を考慮する必要があります。 const 静的変数のすべての利点が得られます + コンパイラの型チェックを有利に使用できます。
私の2セント
個人的には、Unity などの依存性注入フレームワークを使用します。それらはすべてコンテナー内のシングルトン アイテムを構成でき、クラスの依存性からインターフェイスの依存性に移行することで結合を改善します。
パブリック コンストラクターを非表示にし、プライベートな静的フィールドを追加してこのインスタンスのみを保持し、静的ファクトリ メソッドを (遅延イニシャライザーを使用して) 追加してその単一のインスタンスを返すことにより、
public class MySingleton
{
private static MySingleton sngltn;
private static object locker;
private MySingleton() {} // Hides parameterless ctor, inhibits use of new()
public static MySingleton GetMySingleton()
{
lock(locker)
return sngltn?? new MySingleton();
}
}