【发布时间】:2011-04-26 03:51:20
【问题描述】:
现在我遇到了一个我刚刚编写的用于 ASP.NET MVC 的 Singleton 的问题——我的 Singleton 看起来像这样:
public sealed class RequestGenerator : IRequestGenerator
{
// Singleton pattern
private RequestGenerator()
{
requestList = new Stack<Request>();
appSettings = new WebAppSettings();
}
private static volatile RequestGenerator instance = new RequestGenerator();
private static Stack<Request> requestList = new Stack<Request>();
// abstraction layer for accessing web.config
private static IAppSettings appSettings = new WebAppSettings();
// used for "lock"-ing to prevent race conditions
private static object syncRoot = new object();
// public accessor for singleton
public static IRequestGenerator Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new RequestGenerator();
}
}
}
return instance;
}
}
private const string REQUESTID = "RequestID";
// Find functions
private Request FindRequest(string component, string requestId)
private List<Request> FindAllRequests(string component, string requestId)
#region Public Methods required by Interface
// Gets and increments last Request ID from Web.Config, creates new Request, and returns RequestID
public string GetID(string component, string userId)
// Changes state of Request to "submitted"
public void SetID(string component, string requestId)
// Changes state of Request to "success" or "failure" and records result for later output
public void CloseID(string component, string requestId, bool success, string result)
// Verifies that Component has generated a Request of this ID
public bool VerifyID(string component, string requestId)
// Verifies that Component has generated a Request of this ID and is owned by specified UserId
public bool VerifyID(string component, string userId, string requestId)
// Returns State of Request ID (Open, Submitted, etc.)
public Status GetState(string component, string requestId)
// Returns Result String of Success or Failure.
public string GetResult(string component, string requestId)
#endregion
}
我的控制器代码如下所示:
public ViewResult SomeAction()
{
private IRequestGenerator reqGen = RequestGenerator.Instance;
string requestId = reqGen.GetID(someComponentName, someUserId);
return View(requestId);
}
我第一次点击控制器时一切正常。 “reqGen”被分配了单例的实例。一个新的 Request 实例被添加到 Singleton 的内部列表中。然后我们返回一个 View()。下次我点击这个控制器的 SomeAction() 时,我希望 Singleton 包含带有我刚刚添加的 SomeClass 实例的 List,但 List 是空的。
发生了什么事?垃圾收集是否吞噬了我的对象?在 ASP.NET MVC 中实现单例模式时有什么特别需要考虑的吗?
谢谢!
编辑:啊,灯泡刚刚亮了。因此,每个新页面请求都发生在一个全新的过程中!知道了。 (我的背景是桌面应用程序开发,所以这对我来说是一个不同的范例......)
EDIT2:当然,这里有更多的说明。我的应用程序需要一个请求编号系统,其中所请求的内容需要一个唯一的 ID,但我没有可用的数据库。但它必须可供每个用户使用以记录每个请求的状态。我还意识到它可以兼作调节会话的一种方式,例如,如果用户双击请求按钮。单例似乎是要走的路,但意识到每个请求都在自己的进程中基本上消除了单例。而且我猜这也消除了静态类,对吧?
EDIT3:好的,我已经添加了我正在使用的实际代码(为了简单起见,减去每个方法的实现......)我希望这更清楚。
EDIT4:我将绿色复选标记授予 Chris,因为我开始意识到应用程序级单例就像拥有一个 Global(并且 global 是邪恶的,对吗?) ——除了开玩笑,最好的选择确实是拥有一个数据库,而 SQLite 似乎是目前最合适的选择,尽管我可以肯定地看到自己将来会迁移到 Oracle 实例。不幸的是,最好的选择是使用 ORM,但这是另一个需要攀登的学习曲线。混蛋。
EDIT5:最后一次编辑,我发誓。 :-)
所以我尝试使用 HttpRuntime.Cache,但惊讶地发现我的缓存不断刷新/失效,无法弄清楚发生了什么。好吧,我被我正在做的其他事情的副作用绊倒了:写到“Web.config”
答案 --> 我不知道,当“web.config”无论如何改变时,应用程序就会重新启动!是的,一切都被扔掉了。我的单身,我的缓存,一切。嘎。难怪没有什么工作正常。看起来写回 web.config 通常是不好的做法,我现在将避免这样做。
再次感谢所有帮助我解决这个难题的人。
【问题讨论】:
-
如果您这样做是为了缓存原因,那么请考虑使用 HttpContext.Current.Cache。
-
这是一个很好的问题!观看 Pretzel 完成向 Web 开发过渡的过程将对许多未来的程序员有所帮助
-
@Chris,是的,我尝试在我的问题和答案中详细解释所有内容,以便每个人都可以从我的课程中学习(另外,当我几个月后不可避免地忘记某些课程时,我可以快速提醒自己我学到了什么... ;-)
标签: asp.net-mvc garbage-collection singleton