2010-05-03 38 views
3

我正在学习将MVP应用于C#中一个简单的WinForms应用程序(只有一种形式),并在static void Main()中创建主要演示者时遇到问题。为了将它作为参数提供给Application.Run(),从Presenter公开一个View是否是一个好主意?应如何为MVP WinForms应用程序的主要演示者调用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(); 
    } 

开始和视图中的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()调用似乎是关闭窗体(和应用程序)的一种不雅的方式。另一种方法是将View作为Presenter的公共属性公开,以便使用Form参数调用Application.Run()。

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

Presenter中的启动和停止方法保持不变。额外的属性添加到返回查看表单:

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(); } 
    } 

的启动和停止方法在View(Windows窗体)将被写成如下:

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

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

任何人都可以建议哪些是更好的方法,为什么?或者有更好的方法来解决这个问题?

+0

我感谢罗杰,Heinzi和妮可为自己宝贵的意见,但我选择了Heinzi的答案终于因为我已经适应了他的答案用两个额外的接口IMainPresenter和IMainView我的实际应用。 – anonymous 2010-05-12 03:29:39

回答

9

什么如下:

// 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();  
}  

这样,你不需要暴露欣赏到外面。另外,观点和主持人都知道这个观点已经开始作为一个“主要形式”,这可能是一个有用的信息。

+1

IMO,演示者或视图界面都不应该知道如何启动windows消息泵。 您只会用不存在的方法膨胀IView接口,如果您正在编写针对伪视图的测试,则必须实施该方法。 – 2010-05-05 15:26:58

+1

将为视图和演示者创建另一个接口,例如IMainView,IMainPresenter仅专门处理StartApplication()和StopApplication()。所以View将实现Iview和IMainView,Presenter将实现IMainPresenter。 – anonymous 2010-05-07 01:34:10

+1

@罗伯斯先生:这是个好主意。您甚至可以制作IView和IPresenter的IMainView和IMainPresenter子接口,因为IMainView始终是IView(与Presenter相同)。 – Heinzi 2010-05-07 05:37:11

5

我会去第二种方法。 你也可以通过简单地将视图转换为void Main来形成额外的属性,因为无论如何你都知道它是一种形式(我没有理由使它更通用,因为它只是启动winform APP)

Application.Run(view as Form); 
1

如果您允许多种方式退出应用程序(例如:用于退出的菜单项),或者您在特定条件下阻止关闭应用程序,情况会变得更复杂。在任何一种情况下,应用程序关闭的实际调用通常应从演示者代码中调用,而不是简单地关闭具体视图。这可以通过使用Application.Run()或Application.Run(ApplicationContext)重载并通过控制反转公开应用程序退出操作来完成。

注册和使用应用程序退出操作的确切方法将取决于您正在使用的IoC机制(例如:服务定位器和/或依赖项注入)。因为你没有提到你的现任国际奥委会的做法可能是什么,这里有一个样本这是独立于任何特定的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(); 
    } 
} 

这种基本方法可以很容易地适应您的首选IoC机制。例如,如果您使用服务定位器,则可能需要考虑至少移除ApplicationActions.ExitApplication属性上的setter,然后将该委托存储在服务定位器中。如果ExitApplication getter仍然存在,它将为服务定位器实例检索器提供一个简单的外观。例如: -

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

最初,我打算将Application.Exit()放置在presenter.Stop()中,但随后决定禁止它,因为这会在用于实现视图的技术(例如演示者中的WinForms)上创建依赖项。在此期间我会研究IoC - 以任何方式用一些伪代码来说明它? – anonymous 2010-05-07 01:28:56

+0

实现的哪个部分需要示例? – 2010-05-11 13:53:10

+0

Application.Exit()部分的IoC部分会很好。谢谢! – anonymous 2010-05-12 02:04:29

相关问题