ASP.NET: хранить свойства класса в сеансе и использовать обработчик сеанса - это хороший дизайн? - PullRequest
2 голосов
/ 28 июля 2010

У меня есть класс с именем 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
}

Вот мой класс 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;
        }
    }
}

Я все еще изучаю OOAD.Я хочу сохранить соответствующие свойства с соответствующими классами.Я также хочу хранить все переменные, хранящиеся в сеансе, в одном месте для удобства обслуживания и для инкапсуляции ключей сеанса и вызовов.

Я чувствую, что мой дизайн слишком связан, хотя.Как я могу сделать это более слабосвязанным?Мой класс editMapUtilities слишком тесно связан с классом SessionHandler?Как бы вы сделали это лучше?

Ответы [ 2 ]

5 голосов
/ 28 июля 2010

Ваша интуиция довольно хороша тем, что ваши классы действительно очень тесно связаны друг с другом. Я собираюсь сослаться на Принципы объектно-ориентированного проектирования Боба Мартина .

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

Мы можем начать с 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
}

И класс SessionHandler теперь будет содержать два новых метода:

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

public static void SetValue(String key, Object val)
{
    currentSession[key] = val;
}

Хорошо, теперь один класс немного более многословен, но ваш класс сеанса стал проще и более гибким. Добавить дополнительные значения просто, но вы можете спросить себя, почему бы просто не использовать прямой сеанс?

Причина, по которой мы реструктурировали классы таким образом, заключалась в том, чтобы приблизить нас на один шаг к чистому разрыву между ними. Получив доступ к нашему классу SessionHandler через свойство, мы можем теперь сделать наш рефакторинг еще на один шаг и использовать Принцип инверсии зависимости .

Вместо того, чтобы полагаться на конкретную реализацию SessionHandler, почему бы нам не абстрагировать хранение переменных Application State за интерфейсом. Тот, который выглядит так:

public interface IApplicationState
{
    public T GetValue<T>(String key);
    public SetValue(String key, Object val);
}

Теперь мы можем просто изменить наше свойство внутри 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
}

Вы можете легко реорганизовать свой класс SessionHandler, чтобы реализовать интерфейс и не быть статичным:

public SessionHandler: IApplicationState { //Implementation }

Или, если вам нужно поддерживать обратную совместимость с другими областями кода, вы можете создать класс-оболочку и оставить SessionHandler статическим:

public SessionHandlerWrapper: IApplicationState
{
    //Call SessionHandler from within this class
}

Теперь верно, что вам придется вручную создавать конкретный экземпляр IApplicationState и передавать его в EditMapUtilities, но теперь ни один класс не зависит от другого. Фактически, если вы когда-нибудь захотите сохранить это в базе данных в будущем, вам просто придется написать новый класс, который реализует IApplicationState. Только вызывающий код должен быть изменен, чтобы использовать новый класс базы данных вместо сеансового.

Теперь вы можете наслаждаться своей новой архитектурой LooSley и минимизированными изменениями, которые вам придется внести, чтобы добавить новые функции.

0 голосов
/ 28 июля 2010

В этом нет ничего плохого. Не беспокойтесь о соединении - классы должны работать вместе, как кирпичи. Люди не волнуются, когда их кирпичи тесно связаны. Сессия и ASP.Net идут рука об руку, как кирпичи и миномет. Другими словами, чтобы написать веб-приложение, нужно добавить состояние HTTP в HTTP.

Я бы сказал, что в этом случае вам может не понадобиться сеанс. Я склонен использовать ViewState для значений, которые меня не волнуют, если клиент может изменить и зарезервировать Session для более конфиденциальных данных (идентификаторы сущностей, переменные на основе ролей)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...