I would like to use Proxy pattern for Session handling.
In my session proxy class I have something like that:
public static class SessionProxy { private const string ThemeNameSessionName = "ThemeName"; private const string PasswordExpirationDaysSessionNam = "PasswordExpirationDays"; /// /// Gets or sets theme name. /// public static string ThemeName { get { if (Session[ThemeNameSessionName] == null) { return String.Empty; } return (string)Session[ThemeNameSessionName]; } set { Session[ThemeNameSessionName] = value; } } /// /// Gets or sets how many days to password expiration. /// public static int PasswordExpirationDays { get { return Convert.ToInt32(Session[PasswordExpirationDaysSessionNam]); } set { Session[PasswordExpirationDaysSessionNam] = value; } } }
so I use it in my app as:
SessionProxy.ThemeName = "Default"; SessionProxy.PasswordExpirationDays = 5;
With this piece of code I have strongly typed sessions mechanism but.. How to remove session without using string literals (like
Session.Remove("ThemeName")
).
In case of strings I can add to my Properties:
set { if (String.IsNullOrEmpty(value)) { Session.Remove(ThemeNameSessionName); } else { Session[ThemeNameSessionName] = value; } }
but in case of other types (int, long, datetime etc.) I can't use null (I don't want to use nullable types).
Can you advice me the best solution of this problem?
The perfect one will be something like that if possible:
Session.Remove([some magic here]SessionProxy.ThemeName[/magic]);
And one thing yet, I need it in .NET 2.0 (though soulution for .NET 3.5 also will be interesting).
Best Answer
Firstly, I would say that the last line of code that you quoted:
Should really read something like:
Since this is all about the proxy pattern, I'd think you'd want to continue to access the
Session
object via the proxy class even when removing items from theSession
rather than accessing theSession
object directly (thereby negating some of the usefulness of the proxy class!) Not sure if the above is just a typo, but thought I'd point it out just in case.To answer your question, one relatively simple way of achieving this is to replace your private string constants inside your proxy class with an enumeration of all of the session variable names that you'd like to define.
For example, altering your code from above:
Note that I've added a
Remove
method that takes aSessionProxyVars
parameter.Some simple code showing this in use:
This way, you continue to access the Session object only through the proxy class (thus maintaining encapsulation) and also giving you the option to remove a particular session variable in a "strongly-typed" way (i.e. without having to resort to string literals).
Of course, one downside to this is that all of your session variables must be "pre-defined" within your enumeration, but that was pretty much the case if you're using private string constants, too.
There's probably another way of doing this involving defining an interface (say,
ISessionVariable<T>
allowing the interface to be both generic (for the strongly-typed datatype) as well as "exposing" a variable name) and having a number of classes implement this interface. The Session Proxy class could then be refactored to allow "injection" of any class implementing theISessionVariable<T>
interface, and allowingget
andset
type operation on thatISessionVariable
implementing class in a strongly-typed way. This allows the Session Proxy class itself to be completely agnostic of the different session variables you'll be using, however, this approach does still require that all of the classes (one for each session variable you're going to use) be pre-defined in advance somewhere within your application to ultimately be "injected" into the Session Proxy class. Since we're only talking about "wrapping" the session object and some variables (the list of which is probably fairly fixed and not too large), I think the interface/injection route is overkill (although arguably better designed and certainly more DRY), and personally, I'd go with theenum
option.