如何在c#中创建一个完美的Singleton类?

时间:2012-04-20 03:16:06

标签: c# model-view-controller design-patterns singleton

我想用Singleton类存储一些数据。据我所研究,单例类只能实例化一次。但它对我不起作用。有人可以更正我的代码:

public class MvcApplication : System.Web.HttpApplication
    {
        Singleton clientsessionidinstance = Singleton.GetInstance();
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }


        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new string[] { "MVCPrj.Controllers" }
            );
        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            LOGICcLASSES.Logic.Auth ca = new LOGICcLASSES.Logic.Auth();
            clientsessionidinstance = Singleton.GetInstance();
            clientsessionidinstance.ClientSessionID = ca.Login(new LOGICcLASSES.Entities.ClientAuthentication()
            {
                IP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"],
                UserName = ConfigurationManager.AppSettings["ClientUserName"],
                Password = ConfigurationManager.AppSettings["ClientPassword"]
            });
        }

        protected void Application_AcquireRequestState(object sender, EventArgs e)
        {
            if (System.Web.HttpContext.Current.Session != null)
            {
                if (!string.IsNullOrEmpty(clientsessionidinstance.ClientSessionID))
                {
                    CurrentUserSession.Store<string>("ClientSessionID", clientsessionidinstance.ClientSessionID);
                }
            }
        }
    }  

所以目标是这个,@ Application_Start我必须登录一个帐户。然后我应该在HttpContext.Current.Session上保存返回字符串 很抱歉,我无法访问HttpContext.Current.Session内的Application_Start,但可以在Application_AcquireRequestState上访问。{。} 我可以使用一个变量来保存返回的字符串,然后在Application_AcquireRequestState中使用它的值,但是最大的问题是,页面加载了吗?两次,所以如果我将使用变量,它将在第二次加载时变为null,但Application_Start仍然会启动一次。
所以我开始使用Singleton类,但仍然在第二次加载时得到null值。

Singleton类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MVCPrj.Areas.WebPage.Logic
{
    public class Singleton
    {
        private static Singleton instance;

        private Singleton() { }

        public static Singleton GetInstance()
        {
            lock (typeof(Singleton))
            {
                instance = new Singleton();
            }
            return instance;
        }

        private string _ClientSessionID;
        public string ClientSessionID
        {
            get { return _ClientSessionID; }
            set { _ClientSessionID = value; }
        }
    }
}  

编辑

此代码在阅读Singleton

后适合我
public class Singleton
{
    private static readonly object _mutex = new object();
    private static volatile Singleton _instance = null;
    private Singleton() { }

    public static Singleton Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_mutex)
                {
                    if (_instance == null)
                    {
                        _instance = new Singleton();
                    }
                }
            }
            return _instance;
        }
    }

    private string _ClientSessionID;
    public string ClientSessionID
    {
        get { return _ClientSessionID; }
        set { _ClientSessionID = value; }
    }
}

7 个答案:

答案 0 :(得分:10)

如果您使用的是.NET4,那么使用System.Lazy通常可以最好地实现“完美单身”。

另请参阅this web page,了解C#中许多不同单例模式的描述及其各种优缺点。

答案 1 :(得分:2)

public static Singleton GetInstance()
    {
        lock (typeof(Singleton))
        {
            instance = new Singleton();
        }
        return instance;
    }

如果成员实例为null,则只需创建新实例。你似乎一直在这样做。

答案 2 :(得分:1)

我总是将这个通用基类用于我的单身人士:

public class SingletonBase<T> where T : class
{
    static SingletonBase()
    {
    }

    public static readonly T Instance =
        typeof(T).InvokeMember(typeof(T).Name,
                                BindingFlags.CreateInstance |
                                BindingFlags.Instance |
                                BindingFlags.Public |
                                BindingFlags.NonPublic,
                                null, null, null) as T;
}

答案 3 :(得分:1)

public sealed class Singleton
{
    public static readonly Singleton Instance =new Singleton();
    private Singleton(){}
}//end

这是我见过的最好的SINGLETON。

它很简单,但在不使用锁的情况下是线程安全的。

您还可以将“实例”设为具有“ _instance ”字段的媒体资源。

答案 4 :(得分:1)

我使用这样的单身人士,我没有问题:

public sealed class Settings
{
    private static readonly Lazy<Settings> lazy =
    new Lazy<Settings>(() => new Settings());

    public static Settings Instance { get { return lazy.Value; } }

    private Settings()
    {
        _fileName = "Settings.ini";
    }
....
}

答案 5 :(得分:1)

<强>的Singleton

using System;

public class Singleton
{
   private static Singleton instance;

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null)
         {
            instance = new Singleton();
         }
         return instance;
      }
   }
}

静态初始化

    public sealed class Singleton
{
   private static readonly Singleton instance = new Singleton();

   private Singleton(){}

   public static Singleton Instance
   {
      get 
      {
         return instance; 
      }
   }
}

多线程单身人士

    using System;

public sealed class Singleton
{
   private static volatile Singleton instance;
   private static object syncRoot = new Object();

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null) 
         {
            lock (syncRoot) 
            {
               if (instance == null) 
                  instance = new Singleton();
            }
         }

         return instance;
      }
   }
}

来源:Implementing Singleton in C#

答案 6 :(得分:0)

实际上,如果新CTOR是默认值(无参数),则可以将其置于变量定义中:

public sealed class Singleton {
   public readonly Singleton Instance = new Singleton();
   ...
}

请参阅Exploring the Singleton Design Pattern