我建议不要使用定义它自己的单例的类,因为这通常意味着您在单元测试期间会很痛苦。
如果你使用一个通用的单例,你将拥有相同的功能,但在测试/远离单例模式(例如去多用户)时有更多的好处。
请注意,单身人士是用委托进行初始化的。这里的基本原理是代理只会被调用一次,即使两个线程在某种程度上同时注册单例...
使用接口可以让您在编写单元测试时更轻松,因为您可以模拟零件你对你的测试感兴趣的单身人士(或者你的超级快速 - 在演示到CEO补丁/调试会话前2分钟)。
它可能是矫枉过正的存储登录/传递元组,但这种模式保存我的培根更多的时间比我关心计数。
public static class Singleton<T>
{
private static T instance;
private static readonly object sync = new object();
static bool registered = false;
public static T Instance
{
get
{
return instance;
}
}
public static void Register(Func<T> constructor)
{
lock (sync)
{
if (!registered)
{
instance = constructor();
registered = true;
}
}
}
}
class Demo
{
class Data
{
public string Pass { get; set; }
public string Login { get; set; }
}
void SimpleUsage()
{
string login = "SEKRIT";
string pass = "PASSWORD";
// setup
Singleton<Data>.Register(() => new Data { Login = login, Pass = pass });
//
var ltCommander = Singleton<Data>.Instance;
}
/// <summary>
/// Using an interface will make the singleton mockable for tests!
/// That's invaluable when you'll want to fix something FAST without running the whole app!
/// </summary>
interface IData
{
string Login { get; }
string Password { get; }
}
class UnitTestFriendlyData : IData
{
public UnitTestFriendlyData(string login, string password)
{
Login = login;
Password = password;
}
public string Login { get; private set; }
public string Password { get; private set; }
}
void SmarterUsage()
{
// same setup, but through the interface.
Singleton<IData>.Register(() => new UnitTestFriendlyData("login", "pass"));
// and same for the retrieval
var data = Singleton<IData>.Instance;
}
void UnitTestSetupWithMoq()
{
// Register a mock.
var mock = new Mock<IData>();
mock.SetupProperty(x => x.Login, "Login");
mock.SetupProperty(x => x.Pass, "Pass");
Singleton<IData>.Register(() => mock.Object);
// and same for the retrieval
var data = Singleton<IData>.Instance;
}
}
确实,值得看看编写几个包含密码的Authentication/ConnectionBroker类,并实际执行与安全性相关的功能,而不是将其分散在整个应用程序中。 –
哦,我在看到您的编辑之前回答。当涉及到安全性时,您绝对*必须*预先处理身份验证并将其转换为可通过Thread.CurrentPrincipal访问的IPrincipal。通过评论来讨论这个问题可能太复杂了,所以如果你需要这方面的帮助,可以问一个新问题,并把我的链接:) –