You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 07:15:08