Это хорошая идея, чтобы создать перечисление для имен ключей значений сеанса? - PullRequest
9 голосов
/ 21 января 2009

вместо того, чтобы

 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

будет лучше?

Ответы [ 7 ]

17 голосов
/ 21 января 2009

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

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

4 голосов
/ 21 января 2009

Как насчет: -

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;
0 голосов
/ 19 марта 2015

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

Это C #, но в конце я разместил несколько автоматически сгенерированных VB.NET.

Лучшие решения, которые я видел (принятый ответ и ответ TheObjectGuy), требуют пользовательского класса, который хранится в переменной Session, а затем извлекается из Session для доступа к его свойствам с помощью чего-то вроде 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, но даже если вы используете более старую версию, вы все равно можете управлять ей, явно передавая propertyName. Кроме того, типы свойств должны быть обнуляемыми, чтобы они действовали точно так же, как стандартные вызовы 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
'=======================================================
0 голосов
/ 14 января 2010

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

0 голосов
/ 21 января 2009

Я использовал такие классы, чтобы создать типизированную оболочку сессии / кэша. Возможно, вам понадобится добавить дополнительный код в 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 # ....

0 голосов
/ 21 января 2009

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

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

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

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

...