ASP.NET:在会话中存储类属性和使用会话处理程序 - 这是一个好的设计吗?

sha*_*tch 2 c# asp.net oop

我有一个名为EditMapUtilities的类.

以下是我想要保留的一些类属性:

public class EditMapUtlities
{
    public static Boolean isInitialEditMapPageLoad
    {
        get { return SessionHandler.isInitialEditMapPageLoad; }
        set { SessionHandler.isInitialEditMapPageLoad = value; }
    }

// REST OF CLASS NOT GERMAIN TO DISCUSSION AND OMITTED
}
Run Code Online (Sandbox Code Playgroud)

这是我的SessionHandler类遵循此帖子 静态会话类和多个用户的模式:

using System.Web.SessionState;


public static class SessionHandler
{
    private static HttpSessionState currentSession
    {
        get
        {
            if (HttpContext.Current.Session == null)
                throw new Exception("Session is not available in the current context.");
            else
                return HttpContext.Current.Session;
        }
    }

    //A boolean type session variable
    private static string _isInitialEditMapPageLoad = "EditMapInitialPageLoad";
    public static bool isInitialEditMapPageLoad
    {
        get 
        {
            if (currentSession[_isInitialEditMapPageLoad] == null)
                return true;
            else
                return (Boolean)currentSession[_isInitialEditMapPageLoad];    
        }
        set
        {
            currentSession[_isInitialEditMapPageLoad] = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我还在学习OOAD.我想保留相关属性的相关属性.我还想将所有Session存储的变量保存在一个地方,以便于维护并封装会话密钥和调用.

我觉得我的设计太融洽了.如何使它更松散耦合?我的editMapUtilities类是否与SessionHandler类紧密耦合?你会怎样做得更好?

Jos*_*osh 5

你的直觉非常好,因为你的班级确实非常紧密地相互耦合.我将引用Bob Martin的面向对象设计原理.

遵循单一责任原则,您希望确保在其中一个类更改时不必更新这两个类.现在两个班级对彼此都知之甚少.

我们可以从EditMapUtilites会话处理程序开始并重构访问,以更准确地传达意图.主要是,应用程序状态作用于用户.此外,我们可以通过使用实现相同目标的方法来更改我们访问这些值的方式,从而减少耦合.

public class EditMapUtlities
{
    //Omitting the wireup details for now
    private SessionHandler ApplicationState {get; set;}

    public static Boolean isInitialEditMapPageLoad
    {
        get { return ApplicationState.GetValue<Boolean>("EditMapInitialPageLoad"); }
        set { ApplicationState.SetValue("EditMapInitialPageLoad", value); }
    }

// REST OF CLASS NOT GERMAIN TO DISCUSSION AND OMITTED
}
Run Code Online (Sandbox Code Playgroud)

SessionHandler类现在将包含两个新的方法:

public static T GetValue<T>(String key)
{
    return currentSession[key] ?? default(T);
}

public static void SetValue(String key, Object val)
{
    currentSession[key] = val;
}
Run Code Online (Sandbox Code Playgroud)

好吧,所以现在一个类稍微冗长一点,但是你的会话类更简单,更灵活.添加其他值很简单,但您可能会问自己为什么不直接使用直接会话?

我们以这种方式重组课程的原因是让我们更接近他们之间的干净休息.通过SessionHandler属性访问我们的类,我们现在可以进一步重构并使用依赖性倒置原则.

SessionHandler为什么我们不抽象在接口后面存储Application State变量,而不是依赖于具体的实现.一个看起来像这样:

public interface IApplicationState
{
    public T GetValue<T>(String key);
    public SetValue(String key, Object val);
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以简单地改变我们内部的属性EditMapUtlities来使用接口,并使用良好的手动依赖注入通过构造函数传递它.

public class EditMapUtlities
{
    //Omitting the wireup details for now
    private IApplicationState ApplicationState {get; set;}

    public EditMapUtilities(IApplicationState appState)
    {
        if(appState == null) throw new ArgumentNullException("appState");

        ApplicationState = appState;
    }

    public static Boolean isInitialEditMapPageLoad
    {
        get { return ApplicationState.GetValue<Boolean>("EditMapInitialPageLoad"); }
        set { ApplicationState.SetValue("EditMapInitialPageLoad", value); }
    }

// REST OF CLASS NOT GERMAIN TO DISCUSSION AND OMITTED
}
Run Code Online (Sandbox Code Playgroud)

您可以轻松地重构您的SessionHandler类以实现接口而不是静态的:

public SessionHandler: IApplicationState { //Implementation }
Run Code Online (Sandbox Code Playgroud)

或者,如果您需要保持与其他代码区域的向后兼容性,您可以创建一个包装类,并将SessionHandler保持为静态:

public SessionHandlerWrapper: IApplicationState
{
    //Call SessionHandler from within this class
}
Run Code Online (Sandbox Code Playgroud)

现在确实你必须手动创建你的具体实例IApplicationState并将其传递给EditMapUtilities,但现在这两个类都不依赖于另一个.事实上,如果你以后想要将它存储在数据库中,你只需编写一个实现的新类IApplicationState.只有调用代码才能更改为使用新数据库类而不是基于会话的数据库类.

现在,您可以享受新的loosley耦合架构以及为添加新功能而必须进行的最小化更改.