#c_sharp #winforms #entity_framework #linq #mvp
Я только начинаю осваивать C#. Сейчас пытаюсь разобраться в аспектах проектирования приложения для работы с базами данных. Практически каждый раз я слышу такую фразу "бизнес-логика должна существовать отдельно от формы". Но я не совсем понимаю как этого добиться при программировании WinForms? Посоветуйте пожалуйста исчерпывающее руководство или литературу на этот счет. UPD: На данный момент удалось понять, что при использовании WinForms необходимо использовать паттерн MVP. И единственный пример использования MVP для WinForm, по которому удалось построить рабочее приложение, я смог найти вот в этом топике Как начать пользоваться MVP + WinForms?. Следую изложенной в нём информации у меня получилось следующее приложение. Можете оценить, насколько у меня получилась правильная реализация применения паттерна MVP и отделения бизнес-логики от формы? View using System.Linq; namespace EFCodeFirstMVP { interface IView { void SetData(IQueryableitems); } } using System; using System.Linq; using System.Windows.Forms; namespace EFCodeFirstMVP { public partial class Form1 : Form, IView { private readonly GoodsPresenter presenter; public Form1() { presenter = new GoodsPresenter(this, new GoodsModel()); InitializeComponent(); } public void SetData(IQueryable items) { dataGridView1.DataSource = items.ToList(); } private void Form1_Load(object sender, EventArgs e) { presenter.LoadData(); } } } Presenter namespace EFCodeFirstMVP { class GoodsPresenter { private readonly IView view; private readonly IModel model; public GoodsPresenter(IView view, IModel model) { this.view = view; this.model = model; } public void LoadData() { var data = model.LoadData(); view.SetData(data); } } } Model using System.Linq; namespace EFCodeFirstMVP { interface IModel { IQueryable LoadData(); } } using System.Linq; namespace EFCodeFirstMVP { class GoodsModel : IModel { public IQueryable LoadData() { Context context = new Context(); var items = from Items in context.Goods select Items; return items; } } } Data using System.Data.Entity; namespace EFCodeFirstMVP { class Context: DbContext { public DbSet Goods { get; set; } public DbSet GoodsList { get; set; } public Context() { Database.SetInitializer(new CreateDatabaseIfNotExists ()); } } public class Goods { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public string Barcode { get; set; } public int Price{ get; set; } } }
Ответы
Ответ 1
Окей, давайте попробуем поговорить об этом вне привязки к WinForms. Смотрите. У вас есть две различные вещи: внутреннее поведение программы, и то, как она показывает это пользователю. Представьте себе, чтобы вы пишете программное обеспечение радара. У вашей программы внутри есть список отслеживаемых самолётов. Вы принимаете информацию с датчиков, обсчитываете её, принимаете решение о том, возник новый самолёт, или ложная цель, или известный вам самолёт переместился. Всё это происходит внутри, и для этого взаимодействие с пользователем не так уж и обязательно. Это внутренняя часть программы, модель. Теперь, вам нужно донести эту информацию до оператора. В каком виде вы будете представлять информацию — в виде распечаток зелёного текста на чёрном фоне, или в виде трёхмерной голографической визуализации — не так уж важно, и модель по существу не зависит от этой части. Поэтому вы должны писать модель так, чтобы модель ничего не знала о представлении. Это не то, чтобы строго обязательно, но это позволяет разделить программу на независимые части, и даёт лёгкость работы с ними. Здесь ещё остаются открытыми вопросы о том, как передавать действия пользователя модели, но это отдельная тема. Посмотрим на более приземлённый пример: работа с базой данных. Точно так же у вас есть модель: база данных, и операции над ней, которые вы собираетесь делать. Это всё организуется в модуль, возможно, навешивается сверху синхронизация и асинхронность, на этом модель можно считать оконченной. Представление должно просто показывать пользователю часть модели принимать у пользователя команды, и доставлять их модели после обновления модели показывать обновлённую информацию Обычно выделяют ещё и промежуточный уровень — бизнес-логику, контроллер, view model, которые занимаются пинанием модели, с тем чтобы представление занималось только представлением.Ответ 2
Когда говорят, что форма/UI/View отделена от логики/модели, то имеется ввиду, что UI определен в отдельном namespace и/или class. При этом View получает минимальное количество информации о модели. View подключается к стандартным интерфейсам модели и таким образом может отслеживать и выводить на экран изменения данных. Ниже пример, в котором модель отделена от View. По таймеру в модель добавляются данные, которые выводятся в View. class View { static public void Show(object model, string member) { // создаем UI var f = new Form(); var g = new DataGridView() { Parent = f, Dock = DockStyle.Fill, DataSource = model, DataMember = member }; f.ShowDialog(); } } class Model { public Model() { // создаем модель - набор данных и правила их обработки var d = new DataSet(); d.ReadXml(new StringReader("")); // создаем таймер, для изменения модели раз в секунду var timer = new Timer() { Interval = 1000 }; // обработчик событий таймера timer.Tick += (s, e) => { var t = d.Tables["row"]; // создаем новую строку var r = t.NewRow(); r[0] = DateTime.Now.Millisecond; // доавляем строку в DataSet. при этом UI обновится сам. t.Rows.Add(r); }; // запускаем таймер timer.Start(); this.DataMember = "row"; this.DataSource = d; } public readonly string DataMember; public readonly object DataSource; } [STAThread] static void Main() { var m = new Model(); // создаем UI и привязываем его к модели View.Show(m.DataSource, m.DataMember); }
Комментариев нет:
Отправить комментарий