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?

¿Fue útil?

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<$type
Public 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 / :

<*>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top