è una buona idea creare un enum per i nomi chiave dei valori di sessione?
-
19-08-2019 - |
Domanda
invece di fare
session("myvar1") = something
session("myvar2") = something
session("myvar3") = something
session("myvar4") = something
sta facendo
enum sessionVar
myvar1
myvar2
myvar3
myvar4
end enum
session(sessionVar.myvar1.tostring) = something
session(sessionVar.myvar2.tostring) = something
session(sessionVar.myvar3.tostring) = something
session(sessionVar.myvar4.tostring) = something
sarebbe meglio?
Soluzione
Invece di usare le costanti per le chiavi di sessione, sto usando il mio oggetto sessione di tipo sicuro, che assomiglia a questo (mi dispiace che sia in C #, vedi sotto per una versione VB):
public class MySession
{
// Private constructor (use MySession.Current to access the current instance).
private MySession() {}
// Gets the current session.
public static MySession Current
{
get
{
MySession session = HttpContext.Current.Session["__MySession__"] as MySession;
if (session == null)
{
session = new MySession();
HttpContext.Current.Session["__MySession__"] = session;
}
return session;
}
}
// My session data goes here:
public string MyString { get; set; };
public bool MyFlag { get; set; };
public int MyNumber { get; set; };
}
Ogni volta che devo leggere / scrivere qualcosa nella / dalla sessione, posso usare il mio oggetto sessione typesafe in questo modo:
string s = MySession.Current.MyString;
s = "new value";
MySession.Current.MyString = s;
Questa soluzione comporta numerosi vantaggi:
- Ho una sessione typesafe (non più cast di tipi)
- Posso documentare tutti i dati basati sulla sessione (commentando le proprietà pubbliche in MySession)
- Quando si aggiunge un nuovo elemento alla sessione, non è necessario cercare la soluzione per verificare se la stessa chiave di sessione è già stata utilizzata altrove.
Aggiornamento: Ecco una versione VB (convertita automaticamente dalla versione C #). Siamo spiacenti, ma non conosco VB e quindi non sapevo come scrivere le proprietà in VB:
Public Class MySession
' Private constructor (use MySession.Current to access the current instance).
Private Sub New()
End Sub
' Gets the current session.
Public Shared ReadOnly Property Current() As MySession
Get
Dim session As MySession = TryCast(HttpContext.Current.Session("__MySession__"), MySession)
If session = Nothing Then
session = New MySession()
HttpContext.Current.Session("__MySession__") = session
End If
Return session
End Get
End Property
' My session data goes here:
Public MyString As String
Public MyFlag As Boolean
Public MyNumber As Integer
End Class
Altri suggerimenti
Solo se quei valori sono correlati. Altrimenti usa semplici vecchie costanti.
Che ne dici di: -
public static class SessionVar
{
public static readonly string myVar1 = "myVar1";
public static readonly string myVar2 = "myVar2";
public static readonly string myVar3 = "myVar3";
public static readonly string myVar4 = "myVar4";
}
Questo ti permette di usare: -
session(SessionVar.myVar1) = something;
Ho usato classi come questa per creare un wrapper di sessione / cache tipizzato. Potrebbe essere necessario aggiungere un codice aggiuntivo per get / set, ma lo lascerò a te.
internal class SessionHelper
{
private const string myVar1Key = "myvar1";
public static int MyVar1
{
get
{
return (int)System.Web.HttpContext.Current.Session[myVar1Key];
}
set
{
System.Web.HttpContext.Current.Session[myVar1Key] = value;
}
}
}
Mi dispiace per il C # ....
Per la semplice rimozione di tutti i riferimenti alla chiave stringa, andrei con costanti globali statiche / condivise visibili nell'ambito dell'applicazione.
Altrimenti, il semplice wrapper fortemente tipizzato per le variabili di sessione è un'alternativa superiore ed è molto più adatto alle OOP considerando che si ottiene la compatibilità con intellisense e Object Browser.
L'unico modo in cui riesco a vedere l'enum di grande valore è quello di essere utilizzato per indicizzare in un array o in un elenco simile. Ma anche allora devi lanciare l'enum su un int.
Quindi, potresti avere un array che carichi all'avvio dell'applicazione con tutte le chiavi delle variabili di sessione e quindi un enum per gli indici. Tuttavia, dato che l'oggetto Session deriva da HttpSessionState, che deriva da IEnumerable, dovresti essere in grado di eseguire un ciclo foreach sulle variabili di sessione, se necessario.
Mi rendo conto che questa domanda è stata posta qualche tempo fa e una "risposta" è già stato scelto. Ma l'ho appena trovato. La risposta di Martin è buona. Tuttavia, per aiutare chiunque si imbatterà in questo in futuro, se vuoi davvero un modo semplice per gestire Session, leggi questo post . Non credo che troverai niente di più semplice.
Ho trovato una soluzione che evita alcuni svantaggi delle altre soluzioni pubblicate mantenendo intatta la struttura delle variabili Session. È semplicemente una scorciatoia sicura per ottenere e impostare variabili di sessione.
È C #, ma alla fine ho pubblicato alcuni VB.NET generati automaticamente.
Le migliori soluzioni che ho visto (la risposta accettata e quella di TheObjectGuy) richiedono una classe personalizzata che viene memorizzata in una variabile Session, quindi viene estratta dalla Session per accedere alle sue proprietà con qualcosa come MySessionClass.Current.MyProperty .
Il problema è che se stai utilizzando (o potresti utilizzare in futuro) qualcosa di diverso da una modalità InProc Session-State (vedi https://msdn.microsoft.com/en-us/library/ms178586%28v=vs.140%29.aspx ), l'intera classe dovrebbe passare attraverso la serializzazione per accedere a una singola proprietà.
Inoltre, ciò significa che perdi le implementazioni IEnumerable e ICollection offerte dalla Sessione effettiva, se ne hai bisogno. Con la mia soluzione, puoi semplicemente accedere alla sessione effettiva se hai bisogno di questa funzionalità.
Puoi facilmente usare queste variabili di sessione e sono di tipo sicuro. Può essere utilizzato insieme a istruzioni come Session [" MyProperty "], che consentiranno la conversione di un progetto esistente un riferimento alla volta. Quindi:
int myInt = (int)Session["MyInt"];
Session["MyInt"] = 3;
diventa:
int myInt = SessionVars.MyInt;
SessionVars.MyInt = 3;
Ecco la classe attuale. CallerMemberName richiede .NET 4.5, ma anche se si utilizza una versione precedente è comunque possibile gestirlo passando esplicitamente propertyName. Inoltre, i tipi di proprietà devono essere nullable per farlo funzionare esattamente come le chiamate Session [" MyProp "] standard perché non impostate
public static class SessionVars
{
private static T Get2<T>([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
if (HttpContext.Current.Session[propertyName] == null)
{
return default(T);
}
return (T)HttpContext.Current.Session[propertyName];
}
private static void Set2<T>(T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
HttpContext.Current.Session[propertyName] = value;
}
public static int MyInt { get { return Get2<int>(); } set { Set2<int>(value); } }
public static bool MyBool { get { return Get2<bool>(); } set { Set2<bool>(value); } }
public static string MyString { get { return Get2<string>(); } set { Set2<string>(value); } }
}
Ho persino scritto uno snippet di codice per facilitare l'aggiunta di queste proprietà:
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippet Format="1.0.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<Header>
<Title>SessionVars Property</Title>
<Author>kevinpo</Author>
<Shortcut>sv</Shortcut>
<Description>Adds a property for use in a SessionVars class</Description>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<Default>int</Default>
</Literal>
<Literal>
<ID>property</ID>
<Default>PropertyName</Default>
</Literal>
</Declarations>
<Code Language="CSharp">
<![CDATA[public static $type$ $property$ { get { return Get2<$typePublic NotInheritable Class SessionVars
Private Sub New()
End Sub
Private Shared Function Get2(Of T)(<System.Runtime.CompilerServices.CallerMemberName> Optional propertyName As String = "") As T
If HttpContext.Current.Session(propertyName) Is Nothing Then
Return Nothing
End If
Return DirectCast(HttpContext.Current.Session(propertyName), T)
End Function
Private Shared Sub Set2(Of T)(value As T, <System.Runtime.CompilerServices.CallerMemberName> Optional propertyName As String = "")
HttpContext.Current.Session(propertyName) = value
End Sub
Public Shared Property MyInt() As Integer
Get
Return Get2(Of Integer)()
End Get
Set
Set2(Of Integer)(value)
End Set
End Property
Public Shared Property MyBool() As Boolean
Get
Return Get2(Of Boolean)()
End Get
Set
Set2(Of Boolean)(value)
End Set
End Property
Public Shared Property MyString() As String
Get
Return Get2(Of String)()
End Get
Set
Set2(Of String)(value)
End Set
End Property
End Class
'=======================================================
'Service provided by Telerik (www.telerik.com)
'Conversion powered by NRefactory.
'Twitter: @telerik
'Facebook: facebook.com/telerik
'=======================================================
gt;(); } set { Set2<$type<*>gt;(value); } }]]>
</Code>
</Snippet>
</CodeSnippet>
Sono un tipo C #, quindi questo VB.NET viene convertito automaticamente da http: //converter.telerik .com / :
<*>