2009-01-21 12 views
9

thay vì làmlà một ý tưởng hay để tạo ra một enum cho các tên khóa của các giá trị phiên?

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

đang làm

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 

sẽ tốt hơn?

+0

tôi khuyên bạn nên tái gắn thẻ như phiên biến và phiên bang là tốt. –

Trả lời

17

Thay vì sử dụng các hằng số cho các phím phiên, Tôi đang sử dụng kiểu an đối tượng session của riêng tôi, trông giống như thế này (xin lỗi đây là trong C#, xem bên dưới để biết phiên bả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; }; 
} 

Bất cứ khi nào tôi cần đọc/ghi một số điều đến/từ phiên giao dịch, tôi có thể sử dụng đối tượng session typesafe của tôi như thế này:

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

kết quả Giải pháp này trong một số ưu điểm:

  • Tôi có một phiên typesafe (không loại-phôi)
  • Tôi có thể ghi lại tất cả dữ liệu dựa trên phiên (bằng cách nhận xét các thuộc tính công khai trong MySession)
  • Khi thêm phần tử mới vào phiên, tôi không phải tìm kiếm giải pháp để kiểm tra xem khóa phiên đã được sử dụng chưa ở một nơi khác.

Cập nhật: Dưới đây là một phiên bản VB (tự động chuyển đổi từ phiên bản C#). Xin lỗi, nhưng tôi không biết VB và vì vậy tôi không biết làm thế nào để viết các thuộc tính trong 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 
+0

Điều này thật sạch sẽ và đơn giản. Tôi thích nó. –

+0

Có lẽ đăng một phiên bản VB cho Fredou. –

+0

Nhược điểm của phương pháp này là bạn không cung cấp một triển khai IEnumerable, nhưng người ta có thể lập luận rằng nó không cần thiết ngoại trừ các loại phức tạp được lưu trữ dưới dạng danh sách của một số loại. –

9

Chỉ khi những giá trị đó có liên quan. Nếu không thì sử dụng các hằng số cũ đơn giản.

+0

Tôi hy vọng cho một phiên loại an toàn trong ASP.Net –

+1

tiếp theo sẽ loại bỏ sự cần thiết của .toString, đó là rất tốt – Fredou

+0

@ Joel: nhìn vào câu trả lời của tôi cho cách tiếp cận của tôi – M4N

4

Làm thế nào về: -

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

này cho phép bạn sử dụng: -

session(SessionVar.myVar1) = something; 
+0

Tại sao bạn thích sử dụng chỉ đọc hơn const cho chuỗi khóa phiên? – BornToCode

0

Đối với điều đơn giản loại bỏ tất cả các chuỗi tài liệu tham khảo quan trọng, tôi sẽ đi với tĩnh toàn cầu/hằng số được chia sẻ hiển thị ở phạm vi ứng dụng.

Nếu không, trình bao bọc đơn giản được nhập mạnh mẽ cho biến phiên là một giải pháp thay thế cao cấp và thân thiện với OOP hơn khi bạn nhận được sự tương thích của Trình duyệt đối tượng và IntelliSense.

Cách duy nhất tôi có thể thấy enum có nhiều giá trị là được sử dụng để lập chỉ mục vào một mảng hoặc danh sách tương tự. Nhưng ngay cả sau đó bạn phải cast enum vào một int.

Vì vậy, bạn có thể có một mảng mà bạn tải lúc khởi động ứng dụng với tất cả các khóa biến phiên của bạn và sau đó là một enum cho các chỉ mục. Tuy nhiên, với điều kiện đối tượng Session xuất phát từ HttpSessionState, có nguồn gốc từ IEnumerable, bạn sẽ có thể thực hiện một vòng lặp foreach qua các biến session, nếu bạn cần.

0

Tôi đã sử dụng các lớp như thế này để tạo trình bao bọc phiên/bộ nhớ cache đã nhập. Bạn có thể cần thêm mã bổ sung vào get/set, nhưng tôi sẽ để lại điều đó cho bạn.

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

Xin lỗi về C# ....

0

Tôi nhận ra câu hỏi này đã được hỏi một thời gian trước và một "câu trả lời" đã được chọn. Nhưng tôi mới bắt gặp nó. Câu trả lời của Martin là tốt. Tuy nhiên, để hỗ trợ bất kỳ ai tình cờ gặp vấn đề này trong tương lai, nếu bạn thực sự muốn có một cách khéo léo để đối phó với Phiên, hãy đọc số post này. Tôi không nghĩ rằng bạn sẽ tìm thấy bất cứ điều gì dễ dàng hơn.

0

Tôi đã đưa ra một giải pháp tránh những nhược điểm nhất định của các giải pháp khác được đăng bằng cách giữ nguyên cấu trúc của các biến Session. Nó chỉ đơn giản là một phím tắt an toàn để nhận và thiết lập các biến Session.

Đó là C#, nhưng tôi đã đăng một số VB.NET được tạo tự động ở cuối.

Các giải pháp tốt nhất mà tôi đã thấy (câu trả lời được chấp nhận và câu trả lời của TheObjectGuy) yêu cầu một lớp tùy chỉnh được lưu trữ trong biến Phiên và sau đó được lấy từ Phiên để truy cập các thuộc tính của nó bằng MySessionClass.Current. Tài sản của tôi.

Vấn đề với điều này là nếu bạn hiện đang sử dụng (hoặc có thể sử dụng trong tương lai) một cái gì đó khác với chế độ Phiên-trạng thái phiên bản (xem https://msdn.microsoft.com/en-us/library/ms178586%28v=vs.140%29.aspx), cả lớp sẽ phải trải qua quá trình tuần tự để truy cập bất động sản.

Ngoài ra, điều đó có nghĩa là bạn mất các triển khai IEnumerable và ICollection được cung cấp bởi Phiên thực tế, nếu bạn cần. Với giải pháp của tôi, bạn chỉ cần truy cập vào Phiên thực tế nếu bạn cần chức năng này.

Bạn có thể dễ dàng sử dụng các biến phiên này và chúng là loại an toàn. Nó có thể được sử dụng cùng với các câu lệnh như Session ["MyProperty"], điều này sẽ cho phép chuyển đổi một dự án hiện tại thành một tham chiếu tại một thời điểm. Vì vậy:

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

trở thành:

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

Đây là lớp thực tế. CallerMemberName yêu cầu .NET 4.5, nhưng ngay cả khi bạn đang sử dụng phiên bản cũ hơn, bạn vẫn có thể quản lý nó bằng cách chuyển tên propertyName một cách rõ ràng. Ngoài ra, các loại của các thuộc tính phải nullable để làm cho nó hoạt động hoàn toàn giống như tiêu chuẩn Session [ "MyProp"] gọi vì một tổ chức phi thiết

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

Tôi thậm chí đã viết một đoạn mã để tạo điều kiện thêm các thuộc tính:

<?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> 

tôi là một anh chàng C#, vì vậy VB.NET đây chỉ là tính năng tự động chuyển đổi bởi 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 
'=======================================================