Лучший способ удалить сеанс, обработанный шаблоном Session Proxy - PullRequest
0 голосов
/ 09 октября 2009

Я хотел бы использовать шаблон Proxy для обработки сеанса.

В моем сессионном прокси-классе у меня есть что-то вроде этого:

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

, поэтому я использую его в своем приложении как:

SessionProxy.ThemeName = "Default";
SessionProxy.PasswordExpirationDays = 5;

С этим фрагментом кода у меня есть строго типизированный механизм сессий, но ... Как удалить сессию без использования строковых литералов (например,

Session.Remove("ThemeName")
). В случае строк я могу добавить в мои свойства:
        set
        {
if (String.IsNullOrEmpty(value))
{
  Session.Remove(ThemeNameSessionName);
}
else
{
            Session[ThemeNameSessionName] = value; 
}
        }

но в случае других типов (int, long, datetime и т. Д.) Я не могу использовать нуль (я не хочу использовать обнуляемые типы).

Можете ли вы посоветовать мне лучшее решение этой проблемы? Если возможно, идеальным будет что-то подобное:

Session.Remove([some magic here]SessionProxy.ThemeName[/magic]);

И еще одна вещь, она мне нужна в .NET 2.0 (хотя также будет интересен soulution для .NET 3.5).

1 Ответ

0 голосов
/ 09 октября 2009

Во-первых, я бы сказал, что последняя строка кода, которую вы цитировали:

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.

...