C# でシングルトンを実装するにはどうすればよいですか?
質問
C# でシングルトン パターンを実装するにはどうすればよいですか?定数といくつかの基本的な関数をプロジェクト内のあらゆる場所で使用するので、そこに入れたいと考えています。それらを「グローバル」にしたいので、作成するすべてのオブジェクトを手動でバインドする必要はありません。
解決
グローバル値を保存するだけで、状態を必要としないメソッドがある場合、シングルトンは必要ありません。クラスとそのプロパティ/メソッドを静的にするだけです。
public static class GlobalSomething
{
public static int NumberOfSomething { get; set; }
public static string MangleString( string someValue )
{
}
}
シングルトンは、状態を持つ通常のクラスがあり、そのうちの1つだけが必要な場合に最も役立ちます。他の人から提供されたリンクは、シングルトンパターンの探索に役立つはずです。
他のヒント
Singleton!= Global
。キーワード static
を探しているようです。
シングルトンは、これらの条件の両方が真である場合にのみ意味を持ちます:
- オブジェクトはグローバル でなければなりません
- オブジェクトの単一インスタンスのみが存在する必要があります
#2は、オブジェクトが1つのインスタンスのみを持つことを好むことを意味しないことに注意してください。 (たとえば、これが真実ではないのは危険です)ただ1つのインスタンスになります。
グローバルが必要な場合は、何らかの(サインルトンでない)オブジェクトのグローバルインスタンスを作成します(または静的オブジェクトなどにします)。 1つのインスタンスのみが必要な場合も、staticが友達です。また、オブジェクトを1つだけインスタンス化します。
とにかく私の意見。
シングルトン実装を本当に単純化できます。これが私が使用しているものです。
internal FooService() { }
static FooService() { }
private static readonly FooService _instance = new FooService();
public static FooService Instance
{
get { return _instance; }
}
うーん、これは少し複雑に思えます。
シングルトンを取得するために、なぜ依存性注入フレームワークが必要なのですか?一部のエンタープライズアプリではIOCコンテナを使用しても問題ありません(もちろん、使いすぎない限り)。しかし、ああ、このパターンを実装していることを知りたいだけです。
常に熱心にインスタンス化せず、静的を返すメソッドを提供するのはなぜですか。上記のコードのほとんどは消えます。古いC2の格言に従ってください-DoTheSimplestThingThatCouldPossiblyWork ...
記事シングルトンデザインパターンの探索 MSDNで入手できます。パターンの実装を簡単にするフレームワークの機能について詳しく説明します。
余談ですが、シングルトンに関するSOの関連資料をご覧ください。
別の場所で説明したシングルトンパターンを使用する必要があるかどうかの問題を無視して、次のようなシングルトンを実装します。
/// <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() {
}
}
疎結合設計が必要な場合、静的シングルトンはほとんどアンチパターンです。可能な場合は避けてください。これが非常に単純なシステムでない限り、 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>();
受け入れられた答えは、ひどい解決策です。少なくとも実際にパターンを実装した人をチェックしてください。
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()が呼び出されるまで静的コンストラクターが呼び出されないため、(正しい方法でインスタンス化された)単一のインスタンスが得られ、事実上遅延します。
あなたが説明しているのは単なる静的な関数と定数です。 ない シングルトン。シングルトン設計パターン (これはほとんど必要ありません) は、次のクラスを記述します。 は インスタンス化されますが、最初に使用するときに自動的に 1 回だけ作成されます。
遅延初期化とチェックを組み合わせて、複数のインスタンス化を防止します。これが実際に役立つのは、ハードウェア デバイスのラッパーなど、物理的に特異な概念をラップするクラスの場合のみです。
静的定数と関数は次のとおりです。インスタンスをまったく必要としないコード。
次のように自問してください。「このクラスは、複数のインスタンスがあれば壊れますか?」答えがノーの場合、シングルトンは必要ありません。
hmmm ...関連する関数を持つ定数はほとんどありません...列挙型を使用して達成することはできませんか?メソッドを使用してJavaでカスタムenumを作成できることはわかっていますが、C#でも同じことが達成できるはずです。直接サポートされていない場合は、プライベートコンストラクタを持つ単純なクラスシングルトンで実行できます
定数が意味的に関連している場合、enum(または同等の概念)を検討する必要があります。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();
}
}
シングルトンパターンを使用して、プロジェクトのクラスを作成しました。使い方はとても簡単です。それがあなたのために働くことを願っています。次のコードを見つけてください。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace TEClaim.Models
{
public class LogedinUserDetails
{
public string UserID { get; set; }
public string UserRole { get; set; }
public string UserSupervisor { get; set; }
public LogedinUserDetails()
{
}
public static LogedinUserDetails Singleton()
{
LogedinUserDetails oSingleton;
if (null == System.Web.HttpContext.Current.Session["LogedinUserDetails"])
{
oSingleton = new LogedinUserDetails();
System.Web.HttpContext.Current.Session["LogedinUserDetails"] = oSingleton;
}
else
{
oSingleton = (LogedinUserDetails)System.Web.HttpContext.Current.Session["LogedinUserDetails"];
}
//Return the single instance of this class that was stored in the session
return oSingleton;
}
}
}
次のように、アプリケーションで上記のコードの変数値を設定できます。
[HttpPost]
public ActionResult Login(FormCollection collection)
{
LogedinUserDetails User_Details = LogedinUserDetails.Singleton();
User_Details.UserID = "12";
User_Details.UserRole = "SuperAdmin";
User_Details.UserSupervisor = "815978";
return RedirectToAction("Dashboard", "Home");
}
そして、このような値を取得できます。
public ActionResult Dashboard()
{
LogedinUserDetails User_Details = LogedinUserDetails.Singleton();
ViewData["UserID"] = User_Details.UserID;
ViewData["UserRole"] = User_Details.UserRole;
ViewData["UserSupervisor"] = User_Details.UserSupervisor;
return View();
}
C#では(スレッドセーフと遅延初期化):
public sealed class MySingleton
{
static volatile Lazy<MySingleton> _instance = new Lazy<MySingleton>(() => new MySingleton(), true);
public static MySingleton Instance => _instance.Value;
private MySingleton() { }
}
public class Singleton
{
private static Singleton _instance;
public static Singleton Instance => _instance ?? (_instance = new Singleton());
}