ASP.net: синглтон-класс, создание экземпляра только один раз за запрос? - PullRequest
3 голосов
/ 31 августа 2011

У меня есть класс с именем UserContext, который отслеживает действия данного пользователя на моем веб-сайте.Это должен быть одноэлементный класс (только один экземпляр на пользователя).В приложении Windows Forms я мог бы написать что-то вроде этого:

Class UserContext

    Public Shared Current As New UserContext()

    Private Sub New(appName As String)

    [...]

End Class

Но в приложении ASP.net это будет доступно всем текущим пользователям.

Если этот классбыли использованы только внутри сущности Page, я мог просто сохранить экземпляр UserContext в переменной Page - он не обязательно должен выживать постбэков.Но другие сущности (которые не знают о Page) также вызывают UserContext, и я бы хотел, чтобы им всем был дан один и тот же экземпляр.

Что я могу сделать, чтобы гарантировать, что класс является толькосоздается один раз за http запрос (или за пользователя)? Могу ли я использовать кеш для этого?

Public Shared Function GetContext() As UserContext
    If HttpContext.Current.Cache("CurrentUserContext") Is Nothing Then HttpContext.Current.Cache("CurrentUserContext") = New UserContext()
    Return HttpContext.Current.Cache("CurrentUserContext")
End Function

Может ли состояние сеанса быть лучшим вариантом?

Кэш и состояние сеанса оба сохраняют постбэки - есть ли другой параметр, который сбрасывается при каждом новом запросе?

Спасибо заВаша помощь!

Ответы [ 3 ]

5 голосов
/ 31 августа 2011

HttpContext.Current.Cache будет доступно всем пользователям.HttpContext.Current.Session для пользователя, но сохраняется для последующих запросов.

Вам необходимо HttpContext.Current.Items:

Public Shared Function GetContext() As UserContext
    If HttpContext.Current.Items("CurrentUserContext") Is Nothing Then HttpContext.Current.Items("CurrentUserContext") = New UserContext()
    Return HttpContext.Current.Items("CurrentUserContext")
End Function

Это обеспечит безопасность для каждого запроса и хранилища кэша пользователя.

1 голос
/ 01 сентября 2011

Вам потребуется стратегия блокировки для обработки одновременных запросов, если вы храните переменную дольше срока действия запроса. Всегда назначайте при чтении и применяйте двойную проверку блокировки для принудительного включения одиночного вызова.

Private ReadOnly lockObj As New Object()
Private Const CurrentUserContextKey As String = "CurrentUserContext"

Public Function GetContext() As UserContext
    Dim session = HttpContext.Current.Session
    Dim userContext = TryCast(session(CurrentUserContextKey), UserContext)
    If userContext Is Nothing Then
        SyncLock lockObj
            userContext = TryCast(session(CurrentUserContextKey), UserContext)
            If userContext Is Nothing Then
                userContext = New UserContext()
                session(CurrentUserContextKey) = userContext
            End If
        End SyncLock
    End If
    Return userContext
End Function
1 голос
/ 31 августа 2011

Вы можете использовать коллекцию HttpContext.Current.Items.

...