#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(IQueryable items);
}
}
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); }
Комментариев нет:
Отправить комментарий