Reputation: 39364
On a multithread application (ASP.NET MVC) I need to have a global settings class which contains constants and values taken from Web.Config.
I would like to have this class static, as singleton ... And locked?
public static class Settings {
public static LoggerSettings Logger;
public static MailerSettings Mailer;
public class LoggerSettings {
public String Levels { get { return ConfigurationManager.AppSettings["Logger.Levels"]; } }
public const String Report = "[email protected]";
} // LoggerSettings
public class MailerSettings {
public String Contact { get { return ConfigurationManager.AppSettings["Mailer.Contact"]; } }
} // MailerSettings
}
I think I should implement a double lock? No?
I am not sure the best way to do this. Could I, please, get some help?
Thank You, Miguel
Upvotes: 1
Views: 1710
Reputation: 4259
Take a look at Jon Skeet's article Implementing the Singleton Pattern in C#
Simplest and good enough option:
public sealed class Settings
{
private static readonly Settings instance = new Settings();
public LoggerSettings Logger { get; private set; }
public MailerSettings Mailer { get; private set; }
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Settings()
{
}
private Settings()
{
Logger = new LoggerSettings();
Mailer = new MailerSettings();
}
public static Settings Instance { get { return instance;} }
}
public class LoggerSettings {
public LoggerSettings()
{
Levels = ConfigurationManager.AppSettings["Logger.Levels"];
}
public String Levels { get; private set; }
public const String Report = "[email protected]";
}
// Mailer settings would look similar
As you are only reading data from this instance you don't need any locking. The singleton instance is created before any other thread can access it so no need to lock there also.
Usage:
Settings.Instance.Mailer.Contact
Upvotes: 1
Reputation: 659994
I would like to have this class static, as singleton
To implement a singleton correctly in C#, see Jon Skeet's excellent summary of what does and does not work:
http://csharpindepth.com/Articles/General/Singleton.aspx
I think I should implement a double lock? No?
No. Double-checked locking is a low-lock technique and therefore insanely dangerous on weak memory model hardware. The moment you stray even the slightest from a "blessed" pattern you have abandoned all hope of the program behaving predictably.
The only circumstances under which I would use double-checked locking are when all of the following are true:
Lazy<T>
that has acceptable performance? At least you know that CompareExchange and Lazy<T>
were written by experts and enforce memory barriers appropriately on all hardware. Don't use double-checked locking if there is a better tool already implemented.Upvotes: 10
Reputation: 561
if you like it static and as Singleton, try it this way:
public static class Settings {
private static readonly object LockObject = new object();
private static LoggerSetting LoggerInstance;
public static LoggerSetting LoggerSettings {
get {
lock (LockObject) {
if (LoggerInstance == null)
LoggerInstance = new LoggerInstance();
return LoggerInstance;
}
}
}
public class LoggerSetting {
public String Levels {
get { return ConfigurationManager.AppSettings["Logger.Levels"]; }
}
public const String Report = "[email protected]";
}
}
and use it by:
string x = Settings.LoggerSEttings.Report;
Upvotes: 1
Reputation: 2666
if you'd still like to go ahead and have a singleton instance
public class MySettings{
private static Object lockObj = new Object();
private MySettings() {} // private .ctor
private static MySettings _instance;
public static MySettings MySingleSettings{
get{
if(_instance == null){
lock(lockObj){
if(_instance == null)
_instance = new MySettings();
}
}
return _instance;
}
}
Upvotes: -1
Reputation: 8107
as I see, you only read the data. So you need not lock here IMO. Use static constructor to init your variables, like Report (made it also static).
Upvotes: 5