代码之家  ›  专栏  ›  技术社区  ›  anonymous

MVP WinForms应用程序的主要演示者应该如何调用application.run()?

  •  3
  • anonymous  · 技术社区  · 14 年前

    我正在学习用C语言将MVP应用于一个简单的WinForms应用程序(只有一个表单),在创建主演示者时遇到了一个问题。 static void Main() . 为了将视图作为参数提供给application.run(),公开演示者的视图是一个好主意吗?

    目前,我已经实现了一种方法,允许我不将视图作为演示者的属性公开:

        static void Main()
        {
            IView view = new View();
            Model model = new Model();
            Presenter presenter = new Presenter(view, model);
            presenter.Start();
            Application.Run();
        }
    

    演示者中的开始和停止方法:

        public void Start()
        {
            view.Start();
        }
    
        public void Stop()
        {
            view.Stop();
        }
    

    视图中的开始和停止方法(Windows窗体):

        public void Start()
        {
            this.Show();
        }
    
        public void Stop()
        {
            // only way to close a message loop called 
            // via Application.Run(); without a Form parameter
            Application.Exit();
        }
    

    application.exit()调用似乎是关闭表单(和应用程序)的不雅方法。另一种选择是将视图公开为演示者的公共属性,以便使用表单参数调用application.run()。

        static void Main()
        {
            IView view = new View();
            Model model = new Model();
            Presenter presenter = new Presenter(view, model);
            Application.Run(presenter.View);
        }
    

    Presenter中的Start和Stop方法保持不变。将添加一个附加属性以将视图作为表单返回:

        public void Start()
        {
            view.Start();
        }
    
        public void Stop()
        {
            view.Stop();
        }
    
        // New property to return view as a Form for Application.Run(Form form);
        public System.Windows.Form View
        {
            get { return view as Form(); }
        }
    

    视图中的开始和停止方法(Windows窗体)将写入如下:

        public void Start()
        {
            this.Show();
        }
    
        public void Stop()
        {
            this.Close();
        }
    

    有人能建议哪种方法更好,为什么?或者有更好的方法来解决这个问题?

    3 回复  |  直到 14 年前
        1
  •  9
  •   Heinzi    14 年前

    下面是什么?

    // view
    public void StartApplication() // implements IView.StartApplication
    { 
        Application.Run((Form)this);
    }
    
    // presenter
    public void StartApplication()
    {
        view.StartApplication();
    }
    
    // main
    static void Main()     
    {     
        IView view = new View();     
        Model model = new Model();     
        Presenter presenter = new Presenter(view, model);     
        presenter.StartApplication();     
    }     
    

    这样,您就不需要将视图暴露在外部。此外,视图和演示者知道此视图已作为“主窗体”启动,这可能是一条有用的信息。

        2
  •  5
  •   Roger Johansson    14 年前

    我会选择第二种方法。 您也可以通过简单地将视图强制转换为void main中的表单来摆脱多余的属性,因为您知道在这一点上它无论如何都是一个表单(我认为没有理由使它比这个更通用,因为它只是启动了winform应用程序)。

    Application.Run(view as Form);
    
        3
  •  1
  •   Nicole Calinoiu    14 年前

    如果您允许多个方法退出应用程序(例如:退出菜单项),或者在某些条件下阻止关闭应用程序,则情况会变得更加复杂。在这两种情况下,应用程序关闭的实际调用通常应该从演示者代码中调用,而不是简单地关闭具体的视图。这可以通过使用application.run()或application.run(applicationContext)重载并通过控制反转公开应用程序退出操作来实现。

    注册和使用应用程序退出操作的确切方法取决于您使用的IOC机制(例如:服务定位器和/或依赖注入)。既然您没有提到您当前的国际奥委会方法,这里有一个独立于任何特定国际奥委会框架的示例:

    internal static class Program
    {
        [STAThread]
        private static void Main()
        {
            ApplicationActions.ExitApplication = Application.Exit;
    
            MainPresenter mainPresenter = new MainPresenter(new MainView(), new Model());
            mainPresenter.Start();
    
            Application.Run(); 
        }
    }
    
    public static class ApplicationActions
    {
        public static Action ExitApplication { get; internal set; }
    }
    
    public class MainPresenter : Presenter
    {
        //...
    
        public override void Stop()
        {
            base.Stop();
    
            ApplicationActions.ExitApplication();
        }
    }
    

    这一基本方法可以很容易地适应您喜欢的国际奥委会方法。例如,如果您使用的是服务定位器,则可能需要考虑至少删除applicationActions.exitApplication属性上的setter,并将委托存储在服务定位器中。如果exitapplication getter要保留,它将为服务定位器实例检索器提供一个简单的外观。例如。:

    public static Action ExitApplication
    {
        get
        {
            return ServiceLocator.GetInstance<Action>("ExitApplication");
        }
    }