在多线程应用程序(ASP.NET MVC)上,我需要一个全局设置类,其中包含从Web.Config中获取的常量和值。
我想让这个类静态,作为单身......并锁定?
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 = "team@xyz.com";
} // LoggerSettings
public class MailerSettings {
public String Contact { get { return ConfigurationManager.AppSettings["Mailer.Contact"]; } }
} // MailerSettings
}
我想我应该实行双锁?否?
我不确定这样做的最佳方法。请问,我可以帮忙吗?
谢谢你, 米格尔
答案 0 :(得分:10)
我希望这个类是静态的,如单身
要在C#中正确实现单例,请参阅Jon Skeet关于哪些有效和无效的优秀摘要:
http://csharpindepth.com/Articles/General/Singleton.aspx
我想我应该实行双锁?否?
没有。双重检查锁定是一种低锁技术,因此在弱内存模型硬件上非常危险。当你偏离“幸福”模式时,你已经放弃了程序预期的所有希望。
我使用双重检查锁定的唯一情况是所有以下情况属实时:
Lazy<T>
?至少你知道CompareExchange和Lazy<T>
是由专家编写的,并在所有硬件上适当地强制执行内存屏障。如果已经实施了更好的工具,请不要使用双重检查锁定。答案 1 :(得分:5)
如我所见,你只读数据。所以你不需要锁定IMO。 使用静态构造函数来初始化变量,例如Report(使它也是静态的)。
答案 2 :(得分:1)
如果您喜欢静态和单身,请尝试这种方式:
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 = "team@xyz.com";
}
}
并使用它:
string x = Settings.LoggerSEttings.Report;
答案 3 :(得分:1)
看看Jon Skeet的文章Implementing the Singleton Pattern in C#
最简单,最好的选择:
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 = "team@xyz.com";
}
// Mailer settings would look similar
由于您只是从此实例中读取数据,因此不需要任何锁定。单例实例是在任何其他线程可以访问之前创建的,因此也不需要锁定它。
用法:
Settings.Instance.Mailer.Contact
答案 4 :(得分:-1)
如果您仍然希望继续使用单例实例
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;
}
}