ASP.net: singleton class, instantiate just once per request?
I have a class called UserContext
that tracks the activities of a given user on my website. It should be a singleton class (just one instance per user). In a Windows Forms application, I'd could write something like this:
Class UserContext
Public Shared Current As New UserContext()
Private Sub New(appName As String)
[...]
End Class
But on an ASP.net app, this would get shared across all current users.
If this class were only being used within a Page entity I could just store the UserContext instance in a Page variable—it doesn't necessarily need to survive postbacks. But other entities (that don't know about Page) also call UserContext, and I'd like them all to be given the same instance.
What can I do to ensure that a class is only instantiated once per http request (or per user)? Could I use the cache for this?
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
Might session state be a better option?
Cache and session state both survive postbacks—is there another option that resets with each new request?
开发者_Python百科Thanks for your help!
HttpContext.Current.Cache
will be shared among all users. HttpContext.Current.Session
is per user but persists for subsequent requests.
You need 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
This will ensure a safe per request and per user cache store.
You can use the HttpContext.Current.Items
collection.
You will need a locking strategy to handle concurrent requests if you are storing the variable for longer than the life of the request. Always assign on your read, and employ double-checked locking to enforce singleton.
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
精彩评论