Попытка уклониться от класса синглтон / бог / менеджер. Не уверен, как я должен поддерживать функциональность, хотя - PullRequest
6 голосов
/ 29 октября 2011

У меня есть класс, который постоянно растет с течением времени.Это называется LayoutManager.

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

public CormantRadDockZone()
{
    ID = String.Format("RadDockZone_{0}", Guid.NewGuid().ToString().Replace('-', 'a'));
    MinHeight = Unit.Percentage(100);
    BorderWidth = 0;
    HighlightedCssClass = "zoneDropOk";
    CssClass = "rightRoundedCorners";
    LayoutManager.Instance.RegisteredDockZones.Add(this);
}

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

Некоторое время спустя я обнаружил, что передаю объект 'Page' между методами.Это было сделано с единственной целью - получить доступ к элементам управления, найденным на странице.Я подумал: ну, у меня уже есть Layout Manager, я просто буду обрабатывать статические элементы управления таким же образом.

Таким образом, мой метод Page_Init теперь выглядит следующим образом:

protected void Page_Init(object sender, EventArgs e)
{
    SessionRepository.Instance.EnsureAuthorized();

    LayoutManager.Instance.RegisteredPanes.Clear();
    LayoutManager.Instance.RegisteredDocks.Clear();
    LayoutManager.Instance.RegisteredDockZones.Clear();
    LayoutManager.Instance.RegisteredSplitters.Clear();
    LayoutManager.Instance.RegisteredSplitBars.Clear();
    LayoutManager.Instance.RegisteredPageViews.Clear();

    LayoutManager.Instance.CheckBox1 = CheckBox1;
    LayoutManager.Instance.CheckBox4 = CheckBox4;

    LayoutManager.Instance.StartEditButton = StartEditButton;
    LayoutManager.Instance.FinishEditButton = FinishEditButton;

    LayoutManager.Instance.RadNumericTextBox1 = RadNumericTextBox1;
    LayoutManager.Instance.RadNumericTextBox2 = RadNumericTextBox2;

    LayoutManager.Instance.LeftPane = LeftPane;
    LayoutManager.Instance.DashboardUpdatePanel = DashboardUpdatePanel;

    LayoutManager.Instance.CustomReportsContainer = CustomReportsContainer;
    LayoutManager.Instance.HistoricalReportsContainer = HistoricalReportsContainer;
    RegenerationManager.Instance.RegenerateReportMenu();

    LayoutManager.Instance.MultiPage = DashboardMultiPage;
    LayoutManager.Instance.MultiPageUpdatePanel = MultiPageUpdatePanel;
    LayoutManager.Instance.TabStrip = DashboardTabStrip;

    RegenerationManager.Instance.RegenerateTabs(DashboardTabStrip);
    RegenerationManager.Instance.RegeneratePageViews();

    LayoutManager.Instance.Timer = RefreshAndCycleTimer;
    LayoutManager.Instance.Timer.TimerEvent += DashboardTabStrip.DoTimerCycleTick;

    RegenerationManager.Instance.RegeneratePageState();
}

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

Я думаю, что хорошим примером этого на практике было бы использование UpdatePanels.Так, например, DashboardUpdatePanel передается LayoutManager.На странице есть элементы управления, которые условно должны привести к обновлению всего содержимого панели мониторинга.

Теперь, на мой взгляд, у меня есть два варианта:

  1. Внутриобъект, который хочет вызвать UpdatePanel.Update (), я повторяю через родительские объекты, проверяя тип и идентификатор, пока не найду соответствующую UpdatePanel.
  2. Я спрашиваю LayoutManager для UpdatePanel.

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

public class LayoutManager
{
    private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    private static readonly LayoutManager _instance = new LayoutManager();
    private LayoutManager() { }

    public static LayoutManager Instance
    {
        get { return _instance; }
    }

    private IList<CormantRadDock> _registeredDocks;
    private IList<CormantRadDockZone> _registeredDockZones;
    private IList<CormantRadPane> _registeredPanes;
    private IList<CormantRadSplitter> _registeredSplitters;
    private IList<CormantRadSplitBar> _registeredSplitBars; 
    private Dictionary<string, StyledUpdatePanel> _registeredUpdatePanels;
    private IList<CormantRadPageView> _registeredPageViews;

    public RadMultiPage MultiPage { get; set; }
    public CormantTimer Timer { get; set; }
    public CormantRadListBox HistoricalReportsContainer { get; set; }
    public CormantRadListBox CustomReportsContainer { get; set; }
    public StyledUpdatePanel MultiPageUpdatePanel { get; set; }
    public CormantRadTabStrip TabStrip { get; set; }
    public RadPane LeftPane { get; set; }
    public StyledUpdatePanel DashboardUpdatePanel { get; set; }
    public RadButton ToggleEditButton { get; set; }

    public CheckBox CheckBox1 { get; set; }
    public CheckBox CheckBox4 { get; set; }
    public RadNumericTextBox RadNumericTextBox1 { get; set; }
    public RadNumericTextBox RadNumericTextBox2 { get; set; }

    public RadButton StartEditButton { get; set; }
    public RadButton FinishEditButton { get; set; }

    public IList<CormantRadDock> RegisteredDocks
    {
        get
        {
            if (Equals(_registeredDocks, null))
            {
                _registeredDocks = new List<CormantRadDock>();
            }

            return _registeredDocks;
        }
    }

    public IList<CormantRadDockZone> RegisteredDockZones
    {
        get
        {
            if (Equals(_registeredDockZones, null))
            {
                _registeredDockZones = new List<CormantRadDockZone>();
            }

            return _registeredDockZones;
        }
    }

    public IList<CormantRadPane> RegisteredPanes
    {
        get
        {
            if (Equals(_registeredPanes, null))
            {
                _registeredPanes = new List<CormantRadPane>();
            }

            return _registeredPanes;
        }
    }

    public IList<CormantRadSplitter> RegisteredSplitters
    {
        get
        {
            if (Equals(_registeredSplitters, null))
            {
                _registeredSplitters = new List<CormantRadSplitter>();
            }

            return _registeredSplitters;
        }
    }

    public IList<CormantRadSplitBar> RegisteredSplitBars
    {
        get
        {
            if (Equals(_registeredSplitBars, null))
            {
                _registeredSplitBars = new List<CormantRadSplitBar>();
            }

            return _registeredSplitBars;
        }
    }

    public Dictionary<string, StyledUpdatePanel> RegisteredUpdatePanels
    {
        get
        {
            if( Equals( _registeredUpdatePanels, null))
            {
                _registeredUpdatePanels = new Dictionary<string, StyledUpdatePanel>();
            }

            return _registeredUpdatePanels;
        }
    }

    public IList<CormantRadPageView> RegisteredPageViews
    {
        get
        {
            if (Equals(_registeredPageViews, null))
            {
                _registeredPageViews = new List<CormantRadPageView>();
            }

            return _registeredPageViews;
        }
    }

    public StyledUpdatePanel GetBaseUpdatePanel()
    {
        string key = MultiPage.PageViews.Cast<CormantRadPageView>().Where(pageView => pageView.Selected).First().ID;
        return RegisteredUpdatePanels[key];
    }

    public CormantRadDockZone GetDockZoneByID(string dockZoneID)
    {
        CormantRadDockZone dockZone = RegisteredDockZones.Where(registeredZone => dockZoneID.Contains(registeredZone.ID)).FirstOrDefault();

        if (Equals(dockZone, null))
        {
            _logger.ErrorFormat("Did not find dockZone: {0}", dockZoneID);
        }
        else
        {
            _logger.DebugFormat("Found dockZone: {0}", dockZoneID);
        }

        return dockZone;
    }

    public CormantRadPane GetPaneByID(string paneID)
    {
        CormantRadPane pane = RegisteredPanes.Where(registeredZone => paneID.Contains(registeredZone.ID)).FirstOrDefault();

        if (Equals(pane, null))
        {
            _logger.ErrorFormat("Did not find pane: {0}", paneID);
        }
        else
        {
            _logger.DebugFormat("Found pane: {0}", paneID);
        }

        return pane;
    }

    public CormantRadDock GetDockByID(string dockID)
    {
        CormantRadDock dock = RegisteredDocks.Where(registeredZone => dockID.Contains(registeredZone.ID)).FirstOrDefault();

        if (Equals(dock, null))
        {
            _logger.ErrorFormat("Did not find dock: {0}", dockID);
        }
        else
        {
            _logger.DebugFormat("Found dock: {0}", dockID);
        }

        return dock;
    }
}

Я на неверном пути?Какие шаги обычно предпринимаются на этом этапе?

EDIT1: я решил начать путь улучшения с поиска элементов управления, которые наименее интегрированы в LayoutManager, и поиска способов разбиения их на отдельные объекты.Так, например, вместо назначения объектов HistoricalReportsContainer и CustomReportsContainer для LayoutManager (который затем используется в RegenerationManager.RegenerateReportMenu), я переместил код в событие RadListBox «Load».Там я проверяю идентификатор элемента управления, который загружается, и реагирую соответственно.Сильное первое улучшение, и удалило 2 элемента управления и метод из LayoutManager!

Ответы [ 2 ]

1 голос
/ 31 октября 2011

Инверсия контроля - это общий подход, который люди используют для решения таких проблем.Ваши зависимости не должны храниться в одном классе стиля Джек-Бауэра, а должны вводиться, например, через конструктор.Посмотрите на контейнеры IoC, такие как Castle Windsor, Unity, NInject или любые другие.

0 голосов
/ 01 ноября 2011

Я не уверен, как это будет взаимодействовать с будущими планами MVC, но рассматривали ли вы вопрос о реорганизации кусков LayoutManager в абстрактный класс, который наследуется от Page, и затем фактические страницы наследуются от этого абстрактного класса?

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