Во-первых, я бы сказал, что последняя строка кода, которую вы цитировали:
Session.Remove([some magic here]SessionProxy.ThemeName[/magic]);
Должно действительно читать что-то вроде:
SessionProxy.Remove([some magic here]SessionProxy.ThemeName[/magic]);
Поскольку все дело в шаблоне прокси, я думаю, что вы захотите продолжать получать доступ к объекту Session
через класс прокси, даже при удалении элементов из Session
вместо доступа к объекту Session
напрямую (тем самым отрицая некоторую полезность прокси-класса!) Не уверен, что вышеприведенное является просто опечаткой, но подумал, что я укажу это на всякий случай.
Чтобы ответить на ваш вопрос, один из относительно простых способов достижения этого состоит в замене ваших личных строковых констант внутри прокси-класса перечислением всех имен переменных сеанса, которые вы хотите определить.
Например, изменив код сверху:
public static class SessionProxy
{
public enum SessionProxyVars {
ThemeName,
PasswordExpirationDays
}
public static string ThemeName {
get {
if (HttpContext.Current.Session[SessionProxyVars.ThemeName.ToString()] == null) {
return String.Empty;
}
return (string)HttpContext.Current.Session[SessionProxyVars.ThemeName.ToString()];
}
set {
HttpContext.Current.Session[SessionProxyVars.ThemeName.ToString()] = value;
}
}
public static int PasswordExpirationDays {
get {
return Convert.ToInt32(HttpContext.Current.Session[SessionProxyVars.PasswordExpirationDays.ToString()]);
}
set {
HttpContext.Current.Session[SessionProxyVars.PasswordExpirationDays.ToString()] = value;
}
}
public static void Remove(SessionProxyVars vartoremove) {
HttpContext.Current.Session.Remove(vartoremove.ToString());
}
}
Обратите внимание, что я добавил метод Remove
, который принимает параметр SessionProxyVars
.
Несколько простых кодов, показывающих это в использовании:
protected void Page_Load(object sender, EventArgs e)
{
SessionProxy.ThemeName = "MyLovelyTheme";
SessionProxy.PasswordExpirationDays = 3;
Response.Write("<br/><br/>");
foreach (string sesskey in HttpContext.Current.Session.Keys) {
Response.Write(sesskey + ": " + HttpContext.Current.Session[sesskey].ToString());
Response.Write("<br/>");
}
SessionProxy.Remove(SessionProxy.SessionProxyVars.ThemeName);
Response.Write("<br/><br/>");
// Enumerate the keys/values of the "real" session to prove it's gone!
foreach (string sesskey in HttpContext.Current.Session.Keys) {
Response.Write(sesskey + ": " + HttpContext.Current.Session[sesskey].ToString());
Response.Write("<br/>");
}
}
Таким образом, вы продолжаете получать доступ к объекту Session только через прокси-класс (таким образом, сохраняя инкапсуляцию), а также давая вам возможность удалить определенную переменную сеанса «строго типизированным» способом (т.е. без необходимости прибегать к строковые литералы).
Конечно, одним из недостатков этого является то, что все ваши переменные сеанса должны быть «предварительно определены» в вашем перечислении, но это в значительной степени имело место, если вы также используете приватные строковые константы.
Вероятно, есть еще один способ сделать это: определить интерфейс (скажем, ISessionVariable<T>
, позволяющий интерфейсу быть как универсальным (для строго типизированного типа данных), так и "выставить" имя переменной) и получить несколько классы реализуют этот интерфейс. Затем класс Session Proxy можно реорганизовать, чтобы разрешить «внедрение» любого класса, реализующего интерфейс ISessionVariable<T>
, и разрешить операции типа get
и set
над этим классом реализации ISessionVariable
строго типизированным способом. Это позволяет самому классу Session Proxy быть полностью независимым от различных переменных сеанса, которые вы будете использовать, однако этот подход все же требует, чтобы все классы (по одному для каждой переменной сеанса, которые вы собираетесь использовать) были предварительно определены заранее где-то в вашем приложении, чтобы в конечном итоге «внедриться» в класс Session Proxy. Поскольку мы говорим только об «обертывании» объекта сеанса и некоторых переменных (список которых, вероятно, довольно фиксирован и не слишком велик), я думаю, что интерфейс / инъекционный путь излишний (хотя, возможно, лучше спроектирован и, конечно, больше * 1033) * DRY ), и лично я бы выбрал вариант enum
.