Дизайн: как информировать диспетчеры о модификации данных в приложении - программирование
Подтвердить что ты не робот

Дизайн: как информировать диспетчеры о модификации данных в приложении

В большой системе на основе mvc есть представления, ответственные за редактирование данных и представлений, отображающих эти данные.

Пример: UserManagementView и UserSelectionView.

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

Мои мысли об этом - это что-то вроде шаблона наблюдателя (который как бы интегрирован в С#), и все контроллеры будут слушателями и в конечном итоге получат уведомление о том, что произошла манипуляция данными.

BindingList<>, например, предоставляет событие ListChanged. Аналогично, интерфейс может быть создан для каждой структуры данных и уведомлять контроллер об изменении. Это добавит накладные расходы (IMO), и я считаю, что это решение сложно поддерживать в большой системе, а также обновление данных в любом случае не является решением.

Какой архитектурный проект может помочь в таких сценариях?

4b9b3361

Ответ 1

Этот вопрос звучит так, будто вы пытаетесь использовать MVC без части модели. Если я неправильно понял, редактирование вашего вопроса, чтобы включить практический пример использования (пример), может помочь нам понять контекст.

В общем, ничто не должно действительно сохраняться/храниться в ваших контроллерах. Поэтому в контроллере не должно быть ничего, что требует "обновления" или "уведомления" (то есть: нет данных). Скорее, данные должны быть в отдельном "модельном" слое, который управляет всеми вашими данными. Затем просмотры, считываемые с уровня модели, для захвата любых данных для этого представления.

Для быстрого обновления ознакомьтесь со страницей wikipedia на MVC, которая имеет красивую классическую блок-схему MVC и простую запись о взаимодействиях компонентов.

Пример обсуждения

Попробуем придумать пример для понимания этой проблемы.

Скажем, у меня есть список пользователей в моем приложении. Этот список может отображаться на:

  • Просмотр списка главного администратора
  • Пользовательский просмотр прав администратора
  • Просмотр личного профиля пользователя
  • Может быть больше?

Каждое из этих представлений запрашивает данные с вашего уровня модели и показывает что-то на экране.

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

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

В случае winforms модельный слой может предоставить что-то вроде упомянутого интерфейса INotifyPropertyChanged, если ваши компоненты пользовательского интерфейса построены так, чтобы распознавать этот интерфейс и обновлять соответственно. Но это довольно зависимый от платформы подход.

Более агностическим подходом к платформе/контексту был бы уже упоминавшийся паб-суб (публикация-подписка). В этом случае каждый метод контроллера, который внесет изменения в модель, также опубликует уведомление об изменениях. Любые представления для этих данных могут прослушивать и отвечать на такое уведомление, обновляя/перезагружая данные представления с уровня модели.

Ответ 2

Я успешно использовал шаблон Опубликовать-подписать шаблон для решения таких проблем. Всякий раз, когда кто-то кого-то модифицирует, кто-то может быть заинтересован в том, чтобы знать, вы поднимаете событие "ObjectWasModified" или что-то более конкретное, если хотите, как "NewUserAdded" и т.д. И тогда каждая подсистема или другая вещь, которая должна знать, когда это происходит, он подписывается на событие такого типа. Вы можете добавить параметр шаблона в объект EventWasModified или дополнительные условия, поэтому каждая система получает только те события, которые действительно заинтересованы.

Ответ 3

Я знаю, что WPF в сочетании с MVVM в значительной степени зависит от INotifyPropertyChanged и дополнительных INotifyCollectionChanged. Возможно, этот простой интерфейс может просто сделать трюк для вас.

Прочитайте об этом здесь. Статья Джоша Смита об основах MVVM, в которой вы можете понять использование INotifyPropertyChanged. Хотя это и в среде WPF, это можно использовать и в WinForms.

Ответ 4

Почему бы вам просто не использовать модель событий, встроенную в .NET? Правильно ли я понимаю вопрос? Ваш вопрос указывает, что вы думаете, что это добавляет много "накладных расходов" (неясно, если вы имеете в виду производительность или развитие), но это решение очень легкое с точки зрения производительности.

class YourModel
{
    //---- event class can contain data elements to update listeners
    public class DataChangedEventArgs : EventArgs
    {
        ...
    }

    //---- this is what the client callback need to look like
    public delegate void DataChangedDelegate(object oSender, DataChangedEventArgs args);

    //---- public event that clients subscribe to
    public event DataChangedDelegate evtDataChanged;

    //---- any changes in YourModel invoke this method to notify clients
    protected void OnChanged(DataChangedEventArgs args)
    {
        if (evtDataChanged != null)
            evtDataChanged(this, args);
    }

    //---- method(s) in your Model that change internal data
    public void ImaDataChanger(...) 
    {
        //---- stuff that changes the data

        OnChanged(args);    //-- notify clients
    }
}

class UserSelectionView
{
    //---- the event callback
    public void DataChangedHandler(object oSender, YourModel.DataChangedEventArgs args)
    {
        //---- process update or refresh data
        //---- UI updates will have to be marshalled to the UI thread
    }

    //---- sign up for events
    public void Subscribe(YourModel model)
    {
        model.evtDataChanged += new YourModel.DataChangedDelegate(DataChangedHandler);
    }
}

У вас есть возможность определять дополнительные события или добавлять данные в DataChangedEventArgs для предоставления информации о типе изменения данных.

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