删除会话处理会话代理模式的最佳方法

问题描述:

我想使用代理模式进行会话处理。删除会话处理会话代理模式的最佳方法

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

 
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,长,日期时间等),我不能使用空(我不想用可空类型)。

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

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

还有一件事呢,我需要它在.NET 2.0(虽然soulution用于.NET 3.5也将是很有意思)。

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

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

真正应该读的东西,如:

因为这是所有关于代理模式,我d认为即使从Session中移除项而不是直接访问Session对象(因此否定了代理类的某些有用性),您仍希望通过代理类继续访问Session对象!不确定是否abov e只是一个错字,但我想我会指出来以防万一。

要回答您的问题,实现此目的的一个相对简单的方法是将您的代理类中的私有字符串常量替换为您想要定义的所有会话变量名称的枚举。

例如,从上改变你的代码:

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>允许接口既是通用的(用于强类型的数据类型)也用于“暴露”变量名)并且具有许多类实现这个接口。会话代理类然后可以被重构,以允许“注入”任何实现ISessionVariable<T>接口的类,并且允许getset类型操作以该类型以强类型方式实现类。这允许会话代理类本身完全不知道你将要使用的不同会话变量,但是,这种方法仍然要求所有的类(每个会话变量一个要使用的类)事先定义在应用程序中的某个地方,最终被“注入”Session Proxy类。由于我们只是在谈论“包装”会话对象和一些变量(其中的列表可能是相当固定的并且不是太大),我认为接口/注入路径是过量的(虽然可以说设计得更好,当然更多的是DRY) ,并亲自,我会去与enum选项。

+0

CraigTP,非常感谢您的解答和例子!它看起来非常适合我。我将为我当前的项目使用第一种方法(枚举)。感谢您的设计建议,我将添加到SessionProxy类SessionProxy.Remove,Clear,Abandon和其他我将使用的类。问候! – binball 2009-10-09 09:51:04