Как организовать взаимодействие основной программы и GUI?

Итак, попробую объяснить, что мне нужно. Есть Windows Forms проект на C#. SDI, несколько кнопок, combo-box, в общем, ничего сложного. Обработчики событий для каждого элемента помещаются в файл Form.cs. Кроме того, в дереве проекта есть ещё несколько файлов, в частности, Program.cs, .designer.cs и т.д., вы это всё и так знаете. А вопрос у меня такой: куда поместить основную логику программы? Где объявлять переменные, которые, например, будут хранить список доступных (подключенных) устройств? Как определить, сколько устройств уже подключено? Как обрабатывать события, связанные с подключением/отключением устройств и т.д., ведь они никак не связаны с GUI и его обработчиком событий. Я бы мог, например, создать функцию поиска доступных устройств, но куда поместить код её вызова? А что, если она должна на протяжении всего времени работы программы обрабатывать события, связанные с появлением/исчезновением устройств? У меня совсем нет опыта разработки программ с графическим интерфейсом и мне правда очень нужна ваша помощь. Всё, что мне удалось найти в настоящий момент - это простенькие туториалы, которые однако дальше размещения кнопок на форме и баловства с чек-боксами не ушли.
  • Вопрос задан
  • 3562 просмотра
Пригласить эксперта
Ответы на вопрос 2
@Sterk
Программист
Я бы посоветовал вам узнать про dependency injection. С использованием его все становится гораздо проще.
Приведу пример организации проекта:
1 Модуль описание интерфейсов для работы
interface ICore {...}
interface IDeviceManager {...}

у этого модуля не должно быть зависимостей
я думаю в нем же можно объявить структуры данных, но у них так же не должны быть зависимостей от других модулей программы
2 Модуль ядро - в нем должна быть реализована вся логика работы с приборами(или еще чем то) как сервис
class Core : ICore {...}
class DeviceManager : IDeviceManager{...}

этот модуль в зависимостях должен иметь только модуль 1
он должен быть автономным - работать в потоках
3 Модуль Gui - здесь есть варианты, но объединяет их одно - использование шаблона проектирование "внедрение зависимостей". Вот сравнение контейнеров. Я использую LightInject он быстр и прост.
Метод запуска окошек с контейнером на примере LightInject.
допустим у вас есть главное окно и окно с приборами
public partial class MyMainForm
{
    private LightInject.IServiceContainer _container;
    public MyMainForm(LightInject.IServiceContainer container)
    {
        _container = container;
    }
    public void ShowDeviceWindow()
    {
         var form = _container.Create<MyDeviceForm>();
         form.Show();
    }
}
public partial class MyDeviceForm
{
    private IDeviceManager _deviceManager;
    public MyDeviceForm(IDeviceManager devicemanager)
    {
        _deviceManager = devicemanager;
    }
    public void ButtonClick()
    {
     // Здесь вы делаете все что хотите и работаете с менеджером
    // Например загружаете список приборов в лист
    foreach(var device in _deviceManager.GetDevices())
        listBox.Add(device.ToString());
    }

для того что бы не создавать все объекты и зависимости окнам руками используем контейнер
если вы используете WinForms то скорее всего это надо прописать в programm.cs
var container = new LightInject.ServiceContainer();
container.RegisterInstance<IServiceContainer>(container);
container.Register<ICore, Core>(new PerContainerLifetime());
container.Register<IDeviceManager, DeviceManager>(new PerContainerLifetime());
var form = container.Create<MyMainForm>();
//Не помню как выводятся окна в WinForms
//Но логика надеюсь понятна
form.Show();

Таким образом у нас любое окно может запросить любой нужный ему интерфейс для работы с ядром\логикой.
Что бы в каждое окно не совать IServiceContainer я бы создал IWindowManager в реализации которой получал бы контейнер и выводил окно что то вроде manager.ShowWindow<MyDeviceForm>(); и всем окнам подсовывал бы его. Так проще контролировать создание окон.
Для WPF я бы мог посоветовать глянуть различным MVVM фрейворки Calibrun.Micro, Catel и тд.
Есть даже модульная система выглядящая как IDE gemini
Не знаю чем обусловлен выбор WinForms, но для него тоже есть фреймворки, но вроде бы в них применяется шаблон MVP.
Для своих нужд я написал клон gemini со своим видением некоторых моментов. Надеюсь это поможет в разделение логики и окон, несколько лет назад я так же искал информацию как же вообще строить окна, но подсказать было некому.

PS: код набирал в текстовом редакторе, могут быть опечатки и неточности.
Ответ написан
Комментировать
@Eddy_Em
Дык, читайте про IPC. Если нужно шустро оперировать с поступающими от одного клиента данными, открываем сокет; если нужно иметь возможность читать асинхронно кучу данных от разных клиентов с большим временем жизни — заводим файловую очередь (типа очереди POSIX); если хватит времени жизни ядра, пользуемся очередями sysV. Ну и еще вагон и маленькая тележка всяких возможностей.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы