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

3
我希望使用单例类存储一些数据。据我所学,单例类只能被实例化一次。但是我的代码似乎并没有起作用。能否有人纠正我的代码:
```html

我希望使用单例类存储一些数据。据我所学,单例类只能被实例化一次。但是我的代码似乎并没有起作用。能否有人纠正我的代码:

```
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 上。
不幸的是,我无法在 Application_Start 中访问 HttpContext.Current.Session,但可以在 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; }
        }
    }
}  

编辑

在阅读单例模式之后,这段代码对我有效。

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

2
不要重复造轮子:http://csharpindepth.com/Articles/General/Singleton.aspx - BrokenGlass
2
完美的单例模式是一个自相矛盾的说法。创建一个工厂。不要创建一个试图理解自己生命周期的类。 - Ritch Melton
7个回答

10
如果您正在使用.NET4,则通常可以使用System.Lazy来实现“完美单例模式”。另请参见此网页,了解C#中许多不同的单例模式及其各自的优缺点。

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

只有在成员实例为空时,才需要创建新实例。你似乎一直在这样做。


lock(typeof(Singleton)){ var mine = Singleton.GetInstance(); } - Ritch Melton
6
不要锁定类型对象! - L.B

1

单例模式

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

来源:在C#中实现单例模式

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

@TheSean 没有公共构造函数。 - Cade Roux
不需要一个基类。只需向MyClass添加一个公共静态属性,返回Singleton<MyClass>.Instance,这样就可以实现延迟初始化了! - erikH
@erikH 是的,那也可以,但 MyClass : SingletonBase(MyClass) 的一部分是它记录了期望。 - Cade Roux

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

这是我见过的最好的单例模式。

它简单而且线程安全,而不需要使用锁。

你还可以将 'Instance' 作为一个属性,带有一个 '_instance' 字段。


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";
    }
....
}

0
其实,如果变量的构造函数是默认的(没有参数),你可以在变量定义中使用 new:
public sealed class Singleton {
   public readonly Singleton Instance = new Singleton();
   ...
}

请查看探索单例设计模式


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接