【Winform】MVP项目架构

MVP架构的原理和设计思路已经有很多人讲过了,我在此不再赘述。本文重点关注winform项目应该怎么样安排项目中的文件。

MVP

文件目录

MyWinFormsApp/

├── Models/
│ ├── Customer.cs
│ ├── Order.cs

├── Data/
│ ├── AppDbContext.cs
│ ├── Migrations/

├── Views/
│ ├── MainForm.cs
│ ├── MainForm.Designer.cs

├── Presenters/
│ ├── MainPresenter.cs

├── Services/
│ ├── DataService.cs

├── Utilities/
│ ├── SerialPortSingleton.cs

├── Resources/
│ ├── logo.png

├── Properties/
│ ├── AssemblyInfo.cs

├── Program.cs
├── App.config

  • Models: 存放数据模型类和 Entity 类。

  • Data: 存放 DbContext 类和数据访问相关的代码。

  • Views: 存放 WinForms 窗体及 UI 相关文件。

  • Presenters: 存放 Presenter 类。

  • Services: 存放业务逻辑和数据操作类。

  • Utilities: 存放通用工具类。

  • Resources: 存放资源文件,如图片、图标等。

  • Properties: Visual Studio 默认生成,存放项目属性相关文件。

逻辑

我刚开始学习 Winform 的MVP 架构的时候,很难理解以下几个问题

逻辑和UI分离

每次看到逻辑和 UI 分离,总是以为是程序会执行两个线程一个用于ui显示和操作,另一个线程只负责逻辑。这样的想法是不对的ui和逻辑分离并不需要进行多线程操作就像异步不一定是多线程一样。

因为 WinForms ,UI 更新必须在主线程上进行,这也是 WinForms 的 UI 线程,Presenter 在需要与 View 交互时,也需要在主线程上操作,实际上Presenter在同一个线程中。

如果 Presenter 执行耗时操作,例如网络请求或数据处理,建议在后台线程中执行,并在操作完成后使用 Invoke 方法将结果传回 UI 线程。例如:

1
2
3
4
5
6
7
8
public void LoadData()
{
Task.Run(() =>
{
var data = _service.GetData();
_view.Invoke(new Action(() => _view.DisplayData(data)));
});
}

Presenters和Presenters之间到底是怎么联系的

有时候会有这样的想法:我在 Presenters 用了一个 Model 在另外的 Presenters 中也使用了同一个Model这是怎么实现的呢?

通过传递参数把需要的Model传递给另外一个Presenters

Model和View的关系

他们之间是相互不依赖的,不是View一定要对应一个Model,也不是一个Model只能对应一个View。但是一般情况下Model和View会同时创建传递给Presenters,由Presenters来负责他们之间的交互。

Service有什么用

一般是对Model的再次封装,通常出现在Model需要通过数据库获取的情况,或者Model的数据需要再次加工。

在MVP架构中使用ORM框架

直接把Entity当成Model使用就行了。

使用单例担心会被销毁

想什么呢?单例是静态的不会自动回收。