【问题标题】:Best method to remove session handled by Session Proxy pattern删除会话代理模式处理的会话的最佳方法
【发布时间】:2010-12-05 06:36:40
【问题描述】:

我想使用代理模式进行会话处理。

在我的会话代理类中,我有类似的东西:

公共静态类 SessionProxy { 私有常量字符串 ThemeNameSessionName = "ThemeName"; 私人常量字符串 PasswordExpirationDaysSessionNam = "PasswordExpirationDays"; /// /// 获取或设置主题名称。 /// 公共静态字符串 ThemeName { 得到 { 如果(会话 [主题名称会话名称] == 空) { 返回字符串。空; } 返回(字符串)会话[主题名称会话名称]; } 放 { 会话[主题名称会话名称] = 值; } } /// /// 获取或设置密码过期的天数。 /// 公共静态 int PasswordExpirationDays { 得到 { return Convert.ToInt32(Session[PasswordExpirationDaysSessionNam]); } 放 { 会话[PasswordExpirationDaysSessionNam] = 值; } } }

所以我在我的应用程序中使用它:

SessionProxy.ThemeName = "默认"; SessionProxy.PasswordExpirationDays = 5;

通过这段代码,我有强类型会话机制,但是.. 如何在不使用字符串文字的情况下删除会话(如

Session.Remove("ThemeName")
)。 如果是字符串,我可以添加到我的属性中: 放 { 如果(字符串.IsNullOrEmpty(值)) { Session.Remove(ThemeNameSessionName); } 别的 { 会话[主题名称会话名称] = 值; } }

但对于其他类型(int、long、datetime 等),我不能使用 null(我不想使用可为 null 的类型)。

你能告诉我这个问题的最佳解决方案吗? 如果可能的话,完美的应该是这样的:

Session.Remove([这里有些神奇]SessionProxy.ThemeName[/magic]);

还有一件事,我在 .NET 2.0 中需要它(尽管 .NET 3.5 的解决方案也会很有趣)。

【问题讨论】:

    标签: asp.net session proxy c#-2.0 design-patterns


    【解决方案1】:

    首先,我想说的是你引用的最后一行代码:

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

    请注意,我添加了一个采用SessionProxyVars 参数的Remove 方法。

    一些简单的代码展示了它的使用:

    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&lt;T&gt; 允许接口既是通用的(对于强类型数据类型)也可以“公开”一个变量名)并具有许多类实现这个接口。然后可以重构会话代理类以允许“注入”任何实现ISessionVariable&lt;T&gt; 接口的类,并允许以强类型的方式对该ISessionVariable 实现类进行getset 类型操作。这允许会话代理类本身完全不知道您将使用的不同会话变量,但是,这种方法仍然需要所有类(您将要使用的每个会话变量一个)都是预先的预先在应用程序中的某个地方定义,最终被“注入”到 Session Proxy 类中。由于我们只是在谈论“包装”会话对象和一些变量(这些变量的列表可能相当固定且不太大),我认为接口/注入路线是多余的(尽管可以说设计得更好,当然更多@987654321 @),就个人而言,我会选择 enum 选项。

    【讨论】:

    • CraigTP,非常感谢您的解决方案和示例!它看起来很适合我。我将为我当前的项目使用第一种方法(枚举)。感谢您的设计建议,我将添加到我的 SessionProxy 类 SessionProxy.Remove、Clear、Abandon 和其他我将使用的。问候!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 2012-06-28
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    相关资源
    最近更新 更多