WinForms MVP模式中未显式使用的Presenter实例工作原理疑问
WinForms MVP(被动视图)中Presenter实例未直接使用却正常运行的疑问
问题描述
在WinForms MVP(被动视图)项目练习中,遇到如下疑问:代码中实例化了Presenter对象mainPresenter(即new Presenter(mainView, connectionString)),但后续从未直接使用该实例,程序却能正常运行。请问这个实例的去向是哪里?它是如何实现功能的?
主程序代码
using PresentationLayer.Presenters; namespace PresentationLayer { internal static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { // To customize application configuration such as set high DPI settings or default font, // see https://aka.ms/applicationconfiguration. ApplicationConfiguration.Initialize(); //-------------------------------------------- string connectionString = "Data Source=.;Initial Catalog=Music;Integrated Security=True"; IMainView mainView = new MusicForm(); Presenter mainPresenter = new Presenter(mainView, connectionString); //-------------------------------------------- Application.Run((Form)(mainView)); } } }
Presenter类代码
using Models; using ServiceLayer; namespace PresentationLayer.Presenters { public class Presenter { private readonly IMainView _mainView; private readonly IAlbumRepository _albumRepository; private IEnumerable<Album>? _albumList; private readonly BindingSource _bindingSource; //------------------------------------------------------------ public Presenter(IMainView mainView, string connectionString) { _bindingSource = new BindingSource(); _mainView = mainView; _albumRepository = new AlbumRepository(connectionString); _mainView.GetAll += GetAll; _mainView.SearchInAlbums += SearchInAlbums; } //--------------- main functionality -------------------------- private void GetAll(object? sender, EventArgs e) { _albumList = _albumRepository.GetAll(); SetBindingSource(_albumList); } private void SearchInAlbums(object? sender, string fndAlbumsByPhrase) { _albumList = _albumRepository.SearchByAlbum(fndAlbumsByPhrase); SetBindingSource(_albumList); } //------------------helpers / utilities ------------------------ private void SetBindingSource(IEnumerable<Album> coll) { _bindingSource.DataSource = _albumList; _mainView.SetAlbumsBindingSource(_bindingSource); } } }
问题解答
1. Presenter实例的去向
mainPresenter实例并没有被垃圾回收(GC),核心原因是事件订阅建立了强引用关系:
在Presenter的构造函数中,你给mainView的GetAll和SearchInAlbums事件注册了Presenter自身的方法(GetAll、SearchInAlbums)。事件订阅机制会让事件发布者(这里是mainView,也就是运行中的MusicForm窗体)持有订阅者(mainPresenter实例)的强引用。只要mainView处于运行状态(Application.Run启动后直到窗体关闭),mainPresenter就会一直被保留在内存中,不会被GC清理。
2. 功能实现的逻辑
整个流程基于事件驱动+接口交互,步骤如下:
- 初始化绑定:Presenter构造函数执行时,除了初始化数据仓库和视图引用,关键是把视图的事件与自身的业务处理方法绑定在一起。
- 用户交互触发事件:当用户在界面执行操作(比如点击“获取全部”按钮),视图会触发对应的事件(如
GetAll)。 - 业务逻辑执行:事件触发后,会自动调用Presenter中绑定的处理方法,方法内部通过数据仓库获取数据,再调用视图接口的
SetAlbumsBindingSource方法,将数据绑定到视图上,完成界面更新。
内容的提问来源于stack exchange,提问作者Valmont
相关产品推荐
相关产品推荐

