【问题标题】:How should the View pull on the Presenter in the MVP patternMVP 模式中 View 应该如何拉取 Presenter
【发布时间】:2010-04-05 13:52:15
【问题描述】:

我有一个 ASP.NET Web 窗体应用程序,我在视图中使用了一些动态控件,这些控件取决于演示者公开的内容。在这种情况下,视图可以为该数据拉取演示者吗?在考虑可测试性和松散耦合设计时,有什么需要特别注意的吗?

在这种情况下,页面有它自己的页面生命周期,演示者对此一无所知。但是,页面生命周期规定某些事情必须在页面生命周期的特定时刻发生。这闻起来像麻烦……有任何已知的坑吗?

编辑

当我的具体视图遇到 Init 事件时,它将拉动演示者以获取一个集合,这将导致创建一堆 ASP.NET 服务器控件。我想知道这是否是一件特别糟糕的事情......演示者不知道如何响应页面生命周期初始化事件,但如果要使用动态控件填充视图,它必须这样做。

【问题讨论】:

  • 我仍然不清楚为什么演示者需要了解页面生命周期。演示者不只是给视图一个集合吗?视图中没有创建和渲染服务器控件吗?

标签: asp.net mvp


【解决方案1】:

这是一个令人烦恼的问题——当您想要在 ASP.NET Web 表单中使用动态控件时,您必须选择两害相权取其轻。最终,归结为您要做出哪种妥协:视图中的演示者关注点或演示者中的视图关注点。

当我在 Web 表单中工作时,我通常更喜欢后者 - 我接受演示者与 ASP.NET 页面生命周期相关联,并创建一个 InitializeView 方法来执行创建动态控件所需的任何操作:

// Presenter
// This could also be parameterless if you prefer that idiom but 
// then the view needs a SelectedState property that serves up values
// straight from the Form collection, and it won't be obvious why.
public void InitializeView(string selectedState) { 
    if (selectedState != null) {
        view.Counties = dataLayer.GetCounties(selectedState);
    }
}

// View
protected void Page_Init(object sender, EventArgs args) {
    presenter.InitializeView(Request.Form["StateList"]);
    // ... build counties drop-down ...
}

当然,这将演示者的语义与 ASP.NET 生命周期联系在一起,并掩盖了该方法中发生的事情。您可以通过给 InitializeView 一个更具描述性的名称来缓解这​​种情况,例如 ProcessSelectedState,但除非方法名称引用页面生命周期,否则永远不会很明显为什么您不只是使用模型的其余部分获取县(在presenter.LoadModel 或任何你可能称呼它的地方)。

我可以看到替代方案的吸引力:

protected void Page_Init(object sender, EventArgs args) {
    if (Request.Form["StateList"] != null) {
        List<string> counties = presenter.GetCounties(Request.Form["StateList"]);
        // ... build counties drop-down ...
    }
}

Presenter 的语义非常清楚 - 很容易理解 GetCounties 的作用,它与页面生命周期没有任何关系。但是你的视图中有可测试的东西,这很糟糕,这对我来说通常比​​让我的演示者不了解他们的视图引擎更重要。

另一种选择是在页面初始化期间仅加载您的整个模型。您的服务器控制值将不可用,因此您必须从Request.Form 获取任何这些值。不过,这不是惯用的 ASP.NET 经典——它可能会过度混淆,因为大多数 Web 表单开发人员习惯于直接从 Web 控件而不是直接从 POST 数据中获取值。

【讨论】:

  • 感谢您提供非常有见地的回答,可惜我不能给您几个赞。在我看来,这没有对错之分,归结为可测试的内容和重要的属性。
【解决方案2】:

IMO 演示者是视图应该从/绑定到/等的地方获取数据的地方。演示者是要进行单元测试的部分。从您的第二个陈述来看,您可能需要此页面的多个演示者,但我需要更多详细信息才能确定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多