9

而不是做

 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

会更好?

4

7 回答 7

17

我没有使用会话密钥的常量,而是使用我自己的类型安全会话对象,它看起来像这样(抱歉,这是在 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
于 2009-01-21T14:46:00.750 回答
9

仅当这些值相关时。否则使用普通的旧常量。

于 2009-01-21T14:32:50.887 回答
4

怎么样:-

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;
于 2009-01-21T14:42:21.520 回答
0

对于删除所有字符串键引用的简单事情,我将使用在应用程序范围内可见的全局静态/共享常量。

否则,会话变量的强类型简单包装器是一个更好的选择,并且考虑到您获得智能感知和对象浏览器的兼容性,它对 OOP 更加友好。

我可以看到枚举具有很大价值的唯一方法是用于索引数组或类似列表。但即便如此,您也必须将枚举转换为 int。

因此,您可以拥有一个在应用程序启动时加载的数组,其中包含所有会话变量键,然后是索引的枚举。但是,鉴于 Session 对象是从 IEnumerable 派生的 HttpSessionState 派生的,如果需要,您应该能够对会话变量执行 foreach 循环。

于 2009-01-21T14:47:30.403 回答
0

我已经使用这样的类来制作一个类型化的会话/缓存包装器。您可能需要向 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#....

于 2009-01-21T14:47:58.810 回答
0

我意识到这个问题是不久前提出的,并且已经选择了一个“答案”。但我只是遇到了它。马丁的回答很好。但是,为了帮助将来遇到此问题的任何人,如果您真的想要一种巧妙的方式来处理 Session,请阅读这篇文章。我不认为你会发现任何事情更容易。

于 2010-01-14T00:39:34.777 回答
0

我想出了一个解决方案,通过保持 Session 变量的结构完整,避免了发布的其他解决方案的某些缺点。它只是获取和设置 Session 变量的类型安全快捷方式。

它是 C#,但我最后发布了一些自动生成的 VB.NET。

我见过的最佳解决方案(接受的答案和 TheObjectGuy 的答案)需要一个自定义类,该类存储在 Session 变量中,然后从 Session 中拉出以使用 MySessionClass.Current.MyProperty 之类的东西访问其属性。

这样做的问题是,如果您当前正在使用(或将来可能使用)InProc 会话状态模式以外的其他东西(请参阅https://msdn.microsoft.com/en-us/library/ms178586%28v= vs.140%29.aspx),整个类都必须通过序列化来访问单个属性。

此外,如果您需要,这意味着您会丢失实际 Session 提供的 IEnumerable 和 ICollection 实现。使用我的解决方案,如果您需要此功能,您可以简单地访问实际的 Session。

您可以轻松使用这些会话变量,并且它们是类型安全的。它可以与 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
'=======================================================
于 2015-03-19T14:07:24.927 回答