¿Es una buena idea crear una enumeración para los nombres clave de los valores de sesión?
-
19-08-2019 - |
Pregunta
en lugar de hacer
session("myvar1") = something
session("myvar2") = something
session("myvar3") = something
session("myvar4") = something
está haciendo
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
sería mejor?
Solución
En lugar de usar constantes para las claves de sesión, estoy usando mi propio objeto de sesión de tipo seguro, que se ve así (lo siento, esto está en C #, ver más abajo para una versión 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; };
}
Siempre que necesito leer / escribir algo en / desde la sesión, puedo usar mi objeto de sesión typesafe como este:
string s = MySession.Current.MyString;
s = "new value";
MySession.Current.MyString = s;
Esta solución ofrece varias ventajas:
- Tengo una sesión de typesafe (no más tipos de conversión)
- Puedo documentar todos los datos basados ??en sesión (comentando las propiedades públicas en MySession)
- Al agregar un nuevo elemento a la sesión, no tengo que buscar la solución para verificar si la misma clave de sesión ya se usó en otro lugar.
Actualización: Aquí hay una versión VB (convertida automáticamente de la versión C #). Lo siento, pero no conozco VB y no sabía cómo escribir las propiedades en 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
Otros consejos
Solo si esos valores están relacionados. De lo contrario, utilice constantes antiguas simples.
¿Qué tal: -
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";
}
Esto le permite usar: -
session(SessionVar.myVar1) = something;
He usado clases como esta para hacer una sesión escrita / contenedor de caché. Es posible que deba agregar un código adicional al get / set, pero se lo dejaré a usted.
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;
}
}
}
Perdón por el C # ....
Por lo simple de eliminar todas las referencias clave de cadena, iría con constantes globales estáticas / compartidas visibles en el ámbito de aplicación.
De lo contrario, el contenedor simple fuertemente tipado para las variables de sesión es una alternativa superior, y es mucho más amigable con la POO teniendo en cuenta que obtienes compatibilidad con intellisense y Object Browser.
La única forma en que puedo ver que la enumeración es de mucho valor es usarla para indexar en una matriz o una lista similar. Pero incluso entonces tienes que enviar la enumeración a un int.
Por lo tanto, podría tener una matriz que cargue al inicio de la aplicación con todas sus claves de variable de sesión y luego una enumeración para los índices. Sin embargo, dado que el objeto Session se deriva de HttpSessionState, que deriva de IEnumerable, debería poder hacer un bucle foreach sobre las variables de sesión, si es necesario.
Me doy cuenta de que esta pregunta se hizo hace un tiempo y una " respuesta " Ya ha sido elegido. Pero acabo de encontrarlo. La respuesta de Martin es buena. Sin embargo, para ayudar a cualquier persona que se encuentre con esto en el futuro, si realmente desea una forma ingeniosa de lidiar con la Sesión, lea esto publicar . No creo que encuentres nada más fácil.
Se me ocurrió una solución que evita ciertas desventajas de las otras soluciones publicadas al mantener intacta la estructura de las variables de sesión. Es simplemente un acceso directo seguro para escribir y obtener variables de sesión.
Es C #, pero publiqué algunos VB.NET autogenerados al final.
Las mejores soluciones que he visto (la respuesta aceptada y la de TheObjectGuy) requieren una clase personalizada que se almacena en una variable de sesión, y luego se extrae de la sesión para acceder a sus propiedades con algo como MySessionClass.Current.MyProperty .
El problema con esto es que si actualmente está usando (o puede usar en el futuro) algo que no sea un modo de estado de sesión InProc (consulte https://msdn.microsoft.com/en-us/library/ms178586%28v=vs.140%29.aspx ), toda la clase tendría que pasar por la serialización para acceder a una sola propiedad.
Además, eso significa que pierde las implementaciones IEnumerable e ICollection que ofrece la sesión real, si las necesita. Con mi solución, simplemente puede acceder a la sesión real si necesita esta funcionalidad.
Puede usar fácilmente estas variables de sesión y son de tipo seguro. Se puede usar junto con declaraciones como la Sesión [" MyProperty "], que permitirá la conversión de un proyecto existente una referencia a la vez. Entonces:
int myInt = (int)Session["MyInt"];
Session["MyInt"] = 3;
se convierte en:
int myInt = SessionVars.MyInt;
SessionVars.MyInt = 3;
Aquí está la clase real. CallerMemberName requiere .NET 4.5, pero incluso si está utilizando una versión anterior, aún puede administrarlo pasando explícitamente el propertyName. Además, los tipos de las propiedades deben ser anulables para que actúe exactamente igual que las llamadas a la sesión estándar [" MyProp "] porque no se ha configurado
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); } }
}
Incluso escribí un fragmento de código para facilitar la adición de estas propiedades:
<?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>
Soy un chico de C #, así que este VB.NET se convierte automáticamente por http: //converter.telerik .com / :
<*>