我有一个ASP.NET Web窗体应用程序,我在视图中使用了一些动态控件,这取决于演示者公开的内容。在这种情况下,视图是否可以拉动演示者获取该数据?在考虑可测试性和松散耦合设计时,我是否应该格外小心。
在这种情况下,页面具有自己的页面生命周期,并且演示者不知道这一点。但是,页面生命周期决定了某些事情必须发生在页面生命周期的特定时刻。这闻起来像麻烦......任何已知的坑落下?
当我的具体视图点击Init事件时,它将拉动演示者以获得一个集合,这将导致创建一堆ASP.NET服务器控件。我想知道这是否是一件特别糟糕的事情......演示者不知道如何响应页面生命周期初始化事件,但是如果要用动态控件填充视图则必须这样做。
答案 0 :(得分: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数据获取值。
答案 1 :(得分:0)
IMO the presenter是视图应该从/ bind到/ etc获取数据的地方。演示者是将进行单元测试的部分。从你的第二个声明中可能看起来你可能需要多个这个页面的演示者,但我需要更多的细节来确定。