Сейчас у меня проблема с синглтоном, который я только что написал для использования в ASP.NET MVC - мой синглтон выглядит так:
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, который я только что добавил, но вместо этого список пуст.
Что случилось? Сбор мусора поглотил мой объект? Есть ли что-то особенное, что мне нужно учитывать при реализации шаблона Singleton в ASP.NET MVC?
Спасибо!
РЕДАКТИРОВАТЬ: Ах, лампочка только что зажглась. Таким образом, каждый новый запрос страницы происходит в совершенно новом процессе! Понял. (мой опыт в разработке настольных приложений, поэтому для меня это другая парадигма ...)
РЕДАКТИРОВАТЬ 2: Конечно, вот еще несколько разъяснений. Моему приложению требовалась система нумерации запросов, в которой запрашиваемому требовался уникальный идентификатор, но у меня не было доступной БД. Но он должен был быть доступен каждому пользователю для регистрации состояния каждого запроса. Я также понял, что это может стать способом регулирования сессии, скажем, если пользователь дважды щелкнет кнопку запроса. Синглтон показался мне подходящим, но понимание того, что каждый запрос выполняется в своем собственном процессе, в основном устраняет синглтон. И я думаю, что это также устраняет статический класс, верно?
EDIT3: хорошо, я добавил реальный код, с которым я работаю (за исключением реализации каждого метода, для простоты ...) Надеюсь, это будет понятнее.
EDIT4: Я назначаю зеленую галочку Крису, когда начинаю понимать, что синглтон уровня приложения - это все равно, что иметь глобальный (а глобальные - это зло, верно?) - - Шутка в сторону, лучший вариант на самом деле - это иметь БД, и SQLite покажется вам наиболее подходящим, хотя я определенно могу видеть, что в будущем перейду на экземпляр Oracle. К сожалению, тогда лучшим вариантом будет использование ORM, но это еще одна кривая обучения, которую нужно преодолеть. мудак.
EDIT5: Последнее редактирование, клянусь. :-)
Поэтому я попытался использовать HttpRuntime.Cache, но был удивлен, обнаружив, что мой кэш постоянно очищался / становился недействительным и не мог понять, что происходит. Что ж, меня сбило с толку побочным эффектом чего-то другого, что я делал: запись в "Web.config"
Ответ -> Без ведома меня, когда в любом случае изменяется «web.config», приложение перезапускается! Да, все выбрасывается. Мой синглтон, мой кеш, все. Гах. Не удивительно, что ничего не получалось. Похоже, что писать обратно в web.config - это вообще плохая практика, которую я сейчас буду избегать.
Еще раз спасибо всем, кто помог мне с этим затруднением.