问题
I want to store some data with Singleton class. As far as I've studied, singleton class can be instantiated only for once. But it doesn't work for me. Can someone correct my code:
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);
}
}
}
}
So the goal is this, @ Application_Start
I have to log in an account. Then I should save the return string on HttpContext.Current.Session
.
Unfortunately I can't access the HttpContext.Current.Session
inside Application_Start
but it is possible on Application_AcquireRequestState
.
I can use a variable that will hold the returned string and then use its value inside the Application_AcquireRequestState
, but the big problem is this, the page loads? twice, so if I will use a variable, it will become null
at the second load but Application_Start
is still initiated once.
So I came up using a Singleton class, but still I get null values on second load.
Singleton class:
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; }
}
}
}
EDIT
This code works for me after reading 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; }
}
}
回答1:
If you are using .NET4 the "perfect singleton" is often best achieved using System.Lazy.
See also this web page for a description of many different singleton patterns in C# and their various pros and cons.
回答2:
public static Singleton GetInstance()
{
lock (typeof(Singleton))
{
instance = new Singleton();
}
return instance;
}
You only need to create a new instance if the member instance is null. You seem to be doing it all the time.
回答3:
I've always used this generic base class for my singletons:
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;
}
回答4:
I use such singleton and I do not have problems:
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:
public sealed class Singleton
{
public static readonly Singleton Instance =new Singleton();
private Singleton(){}
}//end
this is the best SINGLETON I've ever seen.
it is simple but thread-safe without using locks.
you can also make the 'Instance' as a property with a '_instance' field.
回答6:
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;
}
}
}
Static Initialization
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton(){}
public static Singleton Instance
{
get
{
return instance;
}
}
}
Multithreaded Singleton
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;
}
}
}
Source: Implementing Singleton in C#
回答7:
Actually, you can place the new in the variable definition if its CTOR is default one (no parameters):
public sealed class Singleton {
public readonly Singleton Instance = new Singleton();
...
}
See Exploring the Singleton Design Pattern
来源:https://stackoverflow.com/questions/10239765/how-to-create-a-perfect-singleton-class-in-c