【发布时间】:2014-06-24 00:08:50
【问题描述】:
我在 Jon Skeet's great pattern here 之后使用了一个惰性单例。
此对象的目的是提供对应用程序中所有其他方法的引用。
例如,GetTheme(Context.Current.User.Id) 获取当前用户的主题,以及许多其他方法。
我遇到的问题是当对象已经实例化时如何处理状态变化?
即,如果用户访问网站但未登录,则在创建新用户期间使用Context 对象。
但是,登录后,User 对象为空,因为它已经被实例化了。
我尝试通过以下方式处理此问题,使公共属性引用成为检查 null 引用的私有方法,并尝试确定它是否确实应该是 null。
不幸的是,这变成了一个无限循环并且每次都崩溃。
我之前尝试过让用户对象本身变得懒惰,但由于某些奇怪的原因,它在调用时不会实例化并保持null。
我正在寻找的是,如何让我的 Lazy Singleton 的 User 属性在调用时自行评估,如果它是 null,但能够被填充,则实例化它自己?
条件是,MVC 全局 User 对象属性 User.Identity.Name 不为空,并在加载时传递到会话中以被拉入模型中,并且数据库中存在使用用户名作为用户名的用户键。
public sealed class Context
{
public static Context Current { get { return lazy.Value; } }
private static readonly Lazy<Context> lazy =
new Lazy<Context>(() => new Context());
public UserMeta User { get { return _meta(); } }
private Context()
{
Deployment = GetCurrentDeploymentType();
Device = (Device)HttpContext.Current.Session["CurrentDevice"];
}
private UserMeta _meta()
{
//If the current object is null,
//but the user has been authenticated, populate the object
if (Current.User == null &&
!string.IsNullOrEmpty((string)HttpContext.Current.Session["UserEmail"]))
{
//check that the user is in the database first
var _userTry =
Sql.Read.UserByEmail((string)HttpContext.Current.Session["UserEmail"]);
if (_userTry == null)
{
return new UserMeta(
new UserMeta((string)HttpContext.Current.Session["UserEmail"]));
}
return null;
}
//If the Current Instance already has a populated User Object,
//just use that
else if (Current.User != null)
return Current.User;
else
return null;
}
}
【问题讨论】:
标签: c# design-patterns singleton stack-overflow lazy-evaluation