хорошая ли идея создать перечисление для имен ключей значений сеанса?

StackOverflow https://stackoverflow.com/questions/465522

Вопрос

вместо того, чтобы делать

 session("myvar1") = something
 session("myvar2") = something
 session("myvar3") = something
 session("myvar4") = something

делается

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

было бы лучше?

Это было полезно?

Решение

Вместо использования констант для ключей сеанса я использую свой собственный типобезопасный объект сеанса, который выглядит следующим образом (извините, это на C#, версию 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; };
}

Всякий раз, когда мне нужно прочитать/записать что-либо в/из сеанса, я могу использовать свой типобезопасный объект сеанса следующим образом:

string s = MySession.Current.MyString;
s = "new value";
MySession.Current.MyString = s;

Такое решение дает ряд преимуществ:

  • У меня есть типобезопасный сеанс (больше нет приведения типов)
  • Я могу документировать все данные сеанса (комментируя общедоступные свойства в MySession).
  • При добавлении нового элемента в сеанс мне не нужно искать решение, чтобы проверить, не использовался ли уже где-то еще тот же сеансовый ключ.

Обновлять:Вот версия VB (автоматически преобразованная из версии C#).Извините, но я не знаю VB и поэтому не знаю, как писать свойства в 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

Другие советы

Только если эти значения связаны. В противном случае используйте простые старые константы.

Как насчет: -

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";
}

Это позволяет вам использовать: -

session(SessionVar.myVar1) = something;

Я использовал подобные классы для создания типизированной оболочки сессии / кэша. Возможно, вам понадобится добавить дополнительный код в get / set, но я оставлю это на ваше усмотрение.

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;
        }
    }
}

Извините за C # ....

Для простоты удаления всех ссылок на строковые ключи я бы использовал глобальные статические / общие константы, видимые в области приложения.

В противном случае простая типизированная оболочка со строгой типизацией для переменных сеанса является превосходной альтернативой, и она намного более дружественна к ООП, учитывая, что вы получаете intellisense и совместимость с Object Browser.

Единственный способ увидеть большое значение enum - это использовать его для индексации в массиве или аналогичном списке. Но даже тогда вы должны привести enum к int.

Таким образом, у вас может быть массив, который вы загружаете при запуске приложения со всеми ключами переменных сеанса, а затем перечисление для индексов. Однако, учитывая, что объект Session является производным от HttpSessionState, который является производным от IEnumerable, вы должны иметь возможность просто выполнять цикл foreach над переменными сеанса, если вам нужно.

Я понимаю, что этот вопрос задавали некоторое время назад и " answer " уже был выбран Но я только столкнулся с этим. Ответ Мартина хорош. Однако, чтобы помочь любому, кто столкнется с этим в будущем, если вы действительно хотите ловкий способ иметь дело с сессией, прочитайте это post . Я не думаю, что вы найдете что-нибудь проще.

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

Это C#, но в конце я опубликовал автоматически сгенерированный VB.NET.

Лучшие решения, которые я видел (принятый ответ и ответ TheObjectGuy), требуют специального класса, который хранится в переменной сеанса, а затем извлекается из сеанса для доступа к его свойствам с помощью чего-то вроде MySessionClass.Current.MyProperty.

Проблема в том, что если вы в настоящее время используете (или можете использовать в будущем) что-то иное, чем режим состояния сеанса InProc (см. https://msdn.microsoft.com/en-us/library/ms178586%28v=vs.140%29.aspx), весь класс должен будет пройти сериализацию, чтобы получить доступ к одному свойству.

Кроме того, это означает, что вы потеряете реализации IEnumerable и ICollection, предлагаемые реальным сеансом, если они вам нужны.С помощью моего решения вы можете просто получить доступ к реальному сеансу, если вам нужна эта функция.

Вы можете легко использовать эти переменные сеанса, и они безопасны по типу.Его можно использовать вместе с такими операторами, как Session["MyProperty"], которые позволяют конвертировать существующий проект по одной ссылке за раз.Так:

int myInt = (int)Session["MyInt"];
Session["MyInt"] = 3;

становится:

int myInt = SessionVars.MyInt; 
SessionVars.MyInt = 3;

Вот настоящий класс.Для CallerMemberName требуется .NET 4.5, но даже если вы используете более старую версию, вы все равно можете управлять ею, явно передав имя свойства.Кроме того, типы свойств должны иметь значение NULL, чтобы они действовали точно так же, как стандартные вызовы Session["MyProp"], поскольку неустановленный

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); } }
}

Я даже написал фрагмент кода, чтобы облегчить добавление этих свойств:

<?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$>(); } set { Set2<$type$>(value); } }]]>
    </Code>
  </Snippet>
</CodeSnippet>

Я знаю C#, поэтому этот VB.NET просто автоматически конвертируется http://converter.telerik.com/:

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
'=======================================================
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top