Est-ce une bonne idée de créer une énumération pour les noms de clé des valeurs de session?
-
19-08-2019 - |
Question
au lieu de faire
session("myvar1") = something
session("myvar2") = something
session("myvar3") = something
session("myvar4") = something
fait
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
serait mieux?
La solution
Au lieu d'utiliser des constantes pour les clés de session, j'utilise mon propre objet de session de type sécurisé, qui ressemble à ceci (désolé, ceci est en C #, voir ci-dessous pour une version 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; };
}
Chaque fois que j'ai besoin de lire / écrire quelque chose dans / à partir de la session, je peux utiliser mon objet de session typesafe comme ceci:
string s = MySession.Current.MyString;
s = "new value";
MySession.Current.MyString = s;
Cette solution présente plusieurs avantages:
- J'ai une session typesafe (plus de dactylographie)
- Je peux documenter toutes les données de session (en commentant les propriétés publiques dans MySession)
- Lors de l'ajout d'un nouvel élément à la session, je n'ai pas besoin de rechercher la solution pour vérifier si la même clé de session a déjà été utilisée ailleurs.
Mise à jour: Voici une version VB (convertie automatiquement à partir de la version C #). Désolé, mais je ne connais pas VB et je ne savais donc pas comment écrire les propriétés 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
Autres conseils
Seulement si ces valeurs sont liées. Sinon, utilisez des anciennes constantes simples.
Que diriez-vous de: -
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";
}
Ceci vous permet d'utiliser: -
session(SessionVar.myVar1) = something;
J'ai utilisé des classes comme celle-ci pour créer un wrapper de session / cache typé. Vous devrez peut-être ajouter du code supplémentaire à la commande get / set, mais je vous en laisse le soin.
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;
}
}
}
Désolé pour le C # ....
Pour la simple chose de supprimer toutes les références de clé de chaîne, je choisirais des constantes globales statiques / partagées visibles au niveau de l'application.
Sinon, le wrapper simple fortement typé pour les variables de session est une alternative supérieure, et il est beaucoup plus convivial pour la POO, étant donné que vous obtenez une compatibilité intellisense et le navigateur d'objets.
La seule façon pour moi de voir que l'énum a beaucoup de valeur est d'être utilisé pour indexer dans un tableau ou une liste similaire. Mais même dans ce cas, vous devez convertir l’énum en un int.
Ainsi, vous pourriez avoir un tableau que vous chargez au démarrage de l'application avec toutes vos clés de variable de session, puis un enum pour les index. Toutefois, étant donné que l'objet Session provient de HttpSessionState, qui provient de IEnumerable, vous devriez pouvoir effectuer une boucle foreach uniquement sur les variables de session, si vous en avez besoin.
Je me rends compte que cette question a été posée il y a un moment et un "réponse" a déjà été choisi. Mais je viens de le découvrir. La réponse de Martin est bonne. Cependant, pour aider ceux qui risquent de tomber dans l’avenir, si vous voulez vraiment une façon simple de traiter Session, lisez ceci publier . Je ne pense pas que vous trouverez quelque chose de plus facile.
J'ai proposé une solution qui évite certains inconvénients des autres solutions publiées en conservant la structure des variables de session. Il s'agit simplement d'un raccourci de type sécurisé pour obtenir et définir les variables de session.
C'est C #, mais j'ai posté un fichier VB.NET généré automatiquement à la fin.
Les meilleures solutions que j'ai vues (la réponse acceptée et celle de TheObjectGuy) nécessitent une classe personnalisée qui est stockée dans une variable de session, puis extraite de la session pour accéder à ses propriétés à l'aide de MySessionClass.Current.MyProperty. .
Le problème, c’est que si vous utilisez (ou pouvez utiliser ultérieurement) autre chose qu’un mode d’état de session InProc (voir https://msdn.microsoft.com/en-us/library/ms178586%28v=vs.140%29.aspx ), toute la classe devrait passer par la sérialisation pour accéder à une seule propriété.
De plus, cela signifie que vous perdez les implémentations IEnumerable et ICollection offertes par la session réelle, si vous en avez besoin. Avec ma solution, vous pouvez simplement accéder à la session si vous avez besoin de cette fonctionnalité.
Vous pouvez facilement utiliser ces variables de session et elles sont compatibles avec le type. Il peut être utilisé parallèlement à des instructions telles que Session ["MyProperty"], ce qui permet de convertir un projet existant référence par référence. Donc:
int myInt = (int)Session["MyInt"];
Session["MyInt"] = 3;
devient:
int myInt = SessionVars.MyInt;
SessionVars.MyInt = 3;
Voici la classe actuelle. CallerMemberName requiert .NET 4.5, mais même si vous utilisez une version plus ancienne, vous pouvez toujours le gérer en transmettant explicitement le propertyName. De même, les types des propriétés doivent pouvoir être nullables pour qu’elles agissent exactement de la même manière que les appels de session [[quotprobe; MyProp &]] standard, car un
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); } }
}
J'ai même écrit un extrait de code pour faciliter l'ajout de ces propriétés:
<?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<$typePublic 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>
Je suis un gars C #, ce VB.NET est donc automatiquement converti par http: //converter.telerik. .com / :
<*>