2008-10-29 64 views
24

如何在C#中實現單例模式?我想把我的常量和一些基本功能放在裏面,因爲我在我的項目中使用這些功能。我想讓他們成爲'全球',而不需要手動綁定他們創建的每個對象。如何在C#中實現一個單例?

+1

我想你應該考慮選票並重新考慮你接受的答案。 – 2008-10-29 13:35:09

+0

我不知道 - tvanfosson的回答對於問題的主體來說很好,即使它不是標題。可以說,改變身體或標題以匹配對方將是最好的:) – 2008-10-29 14:04:33

+0

同意你在那 – 2008-10-29 14:49:53

回答

28

如果你只是存儲一些全局值,並有一些不需要狀態的方法,你不需要單例。只需使該類及其屬性/方法靜態。

public static class GlobalSomething 
{ 
    public static int NumberOfSomething { get; set; } 

    public static string MangleString(string someValue) 
    { 
    } 
} 

當你有一個普通的狀態類,但你只需要其中的一個時,單身最有用。其他人提供的鏈接應該有助於探索Singleton模式。

7

Singleton != Global。您似乎在尋找關鍵字static

4

單身才有意義,如果這些條件都爲真:

  1. 的對象必須是全球
  2. 必須有永遠只存在於對象的例如

請注意,#2並不意味着你會對象只有一個實例 - 如果是這種情況,只需實例化一次 - 這意味着有必須(因爲這是非常危險的)只能是單個實例。

如果你想全球化,只需要製作一些(非signleton)對象的全局實例(或使其成爲靜態或其他)。 如果你只想要一個實例,靜態是你的朋友。另外,只需實例化一個對象。

這就是我的意見無論如何。

3

忽視的你是否應該使用Singleton模式,它已在別處討論過這個問題,我想實現這樣的單身:

/// <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() { 

    } 

} 
3

靜態單是相當多的反模式,如果你想要一個鬆散耦合的設計。如果可能的話避免,除非這是一個非常簡單的系統,否則我會建議查看可用的許多依賴注入框架之一,例如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>(); 

接受的答案是順便說一個可怕的解決辦法,至少檢查究竟是誰實施的傢伙該模式。

4

你真的可以簡化單的實現,這是我用:

internal FooService() { }   
    static FooService() { } 

    private static readonly FooService _instance = new FooService(); 

    public static FooService Instance 
    { 
     get { return _instance; } 
    } 
1

你所描述僅僅是靜態函數和常量,單身。單例設計模式(這是很少需要的)描述了一個類,實例化,但只有一次,自動,當第一次使用。

它將延遲初始化與檢查相結合以防止多個實例化。這對於包裝一些物理上單一的概念的類非常有用,例如硬件設備的包裝。

靜態常量和函數就是這樣的:完全不需要實例的代碼。

問問自己:「如果這個類有多個實例,它會中斷嗎?」如果答案是否定的,你不需要單身。

1

嗯...幾乎沒有相關函數的常量......通過枚舉不會更好嗎?我知道你可以使用方法和所有方法在Java中創建一個自定義枚舉,但如果不直接支持,那麼在C#中也應該可以實現,然後可以使用具有私有構造函數的簡單類單例執行。

如果你的常量是語義相關的,你應該考慮枚舉(或等價概念),你將獲得const static變量的所有優點+你將能夠使用你的優勢編譯器的類型檢查。

我2%的

0

通過隱藏公共構造,加入了私有靜態字段來保存這個唯一實例,並添加靜態工廠方法(懶初始化),以返回單一實例

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

就個人而言,我會去尋找一個像Unity這樣的依賴注入框架,它們都可以在容器中配置單例項目,並且可以通過從類依賴轉移到接口依賴來改善耦合。

4

嗯,這一切似乎有點複雜。

爲什麼你需要一個依賴注入框架來獲得一個singleton?使用國際奧委會容器對於某些企業應用程序來說是不錯的選擇(只要它當然不會被過度使用),但是,這傢伙只是想知道實施這種模式的方式。

爲什麼不總是急於實例化,然後提供一個返回靜態的方法,大部分上面寫的代碼就會消失。按照老C2的格言 - DoTheSimplestThingThatCouldPossiblyWork ...

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

} 
2

我喜歡這種模式,雖然它並不能防止有人從創建一個非單一實例。它有時可以更好的教育上使用正確的方法對要英勇的長度,以防止一些博傻使用您的代碼錯誤。在你的團隊開發...

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()之前,靜態構造函數不會被調用。

0

我已經爲我的項目使用Singleton模式寫了一個類。這是非常容易使用。希望它能爲你工作。請查找以下代碼。

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