我正努力使用ASP.net实现依赖注入。我在winforms中创建了一个使用MVP被动视图模式的简单项目。我在网上看到了这种模式的很多变化。我看到的许多示例都让View负责实例化Presenter。其他人让Presenter创建视图。我选择先运行一个单独的winforms项目,然后单击一个按钮,创建我的View,Model和Presenter,并将视图传递给Presenters构造函数。这让我避免三层之间的直接引用,这样它们只保留对接口库的引用。到目前为止一切都那么好,一切都按预期运作我听说如果我设法将视图保持为“愚蠢的”#34;尽管主要逻辑主持在Presenter中,但转移到ASP.net并不会太困难。
我的下一步是在ASP.net webforms中重新创建解决方案,只需用代码隐藏实现我的IView接口的webform替换UI / View。我的所有类都成功编译没有问题,但是当我运行程序时,我得到一个NullReferenceException:对象引用未设置为对象的实例。当Presenter尝试设置文本框的视图属性时,会发生这种情况。似乎尚未创建文本框。如果我将webforms应用程序的开始序列与winforms应用程序进行比较,那么我会看到winforms应用程序在创建时运行View并注册每个控件和属性。即使我对两者使用相同的方法,webform也不会发生这种情况。
这是首先加载的单独的webform:
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using POCOClassLibrary;
using InterfaceLibrary;
using AppointmentModel;
using AppointmentsPresenter;
using WebFormMVP;
namespace WebDriver
{
public partial class WebDriver : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnLaunch_Click(object sender, EventArgs e)
{
IAppointmentView view = new frmAppointmentView();
IAppointmentModel<Appointment> model = new AppointmentsModel();
new AppointmentPresenter(view, model);
view.Show();
}
}
}
加载并显示按钮,然后单击它到达Presenter类(此处未显示):
namespace AppointmentsPresenter
{
//The Presenter is the go-between for the View and Model. It sets the properties in the View to be displayed and
//Stores and Gets the data from the Model. It responds to events raised by the View.
public class AppointmentPresenter
{
private readonly IAppointmentView _view; //references the View Interface
private readonly IAppointmentModel<Appointment> _model; //references the Model Interface
/// <summary>
/// The List of Appointments is created and stored in the Model.
/// In reality we would be using a Database and not a List<>.
/// </summary>
private List<Appointment> appointments;
//maintenace of state:
private int currentIndex = 0;
private bool isNew = true;
private string navigationstatus = "next";
///Presenter constuctor which allows us to pass in the View and Model as interfaces - exposing their events,
/// methods and properties.
public AppointmentPresenter(IAppointmentView view, IAppointmentModel<Appointment> model) //dependencies passed into contructor
{
this._view = view;
this._model = model;
Initialize();
}
private void Initialize()
{
appointments = _model.CreateList(); //Creates and returns List of Appointments in the Model
//lets us manipulate the List that the Model creates.
_view.SaveAppointment += Save_Appointment; //Subscribe to the View events.
_view.NewAppointment += New_Appointment;
_view.PreviousAppointment += Previous_Appointment;
_view.NextAppointment += Next_Appointment;
_view.YesButtonClick += YesButtonClicked;
_view.NoButtonClick += NoButtonClicked;
BlankAppointment();
_view.StatusChange = "Ready";
}
private void BlankAppointment()
{
_view.AppointmentName = string.Empty;
_view.Priority = "Low";
_view.StartDate = null;
_view.DueDate = null;
_view.CompletionDate = null;
_view.Completed = false;
}
当它到达BlankAppointment()方法并尝试设置_view.AppointmentName属性时,就会出现错误并抛出NullReferenceException。
以下是一些View,我试图删除大部分逻辑,只是在这里实现属性和事件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using InterfaceLibrary;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition;
namespace WebFormMVP
{
public partial class frmAppointmentView : System.Web.UI.Page, IAppointmentView
{
public string AppointmentName
{
get { return txtAppointment.Text; }
set { txtAppointment.Text = value; }
}
public string Priority
{
get { return cboPriority.Text; }
set { cboPriority.Text = value; }
}
public string StartDate
{
get { return txtStartDate.Text; }
set { txtStartDate.Text = value; }
}
public string DueDate
{
get { return txtDueDate.Text; }
set { txtDueDate.Text = value; }
}
public string CompletionDate
{
get { return txtCompletionDate.Text; }
set { txtCompletionDate.Text = value; }
}
public bool Completed
{
get { return chkCompleted.Checked; }
set { chkCompleted.Checked = value; }
}
public bool isDirty { get; set; }
public bool NewButtonVisible
{
set { btnNew.Visible = value; }
}
public bool SaveButtonVisible
{
set { btnSave.Visible = value; }
}
public bool NextButtonVisible
{
set { btnNext.Visible = value; }
}
public bool PreviousButtonVisible
{
set { btnPrevious.Visible = value; }
}
public bool YesButtonVisible
{
set { btnYes.Visible = value; }
}
public bool NoButtonVisible
{
set { btnNo.Visible = value; }
}
public string StatusChange
{
set { lblStatus.Text = value; }
}
public event EventHandler<EventArgs> NewAppointment;
public event EventHandler<EventArgs> NextAppointment;
public event EventHandler<EventArgs> NoButtonClick;
public event EventHandler<EventArgs> PreviousAppointment;
public event EventHandler<EventArgs> SaveAppointment;
public event EventHandler<EventArgs> YesButtonClick;
public void Show()
{
this.Show();
}
protected void Page_Load(object sender, EventArgs e)
{
this.isDirty = false;
}
private void btnSave_Click(object sender, EventArgs e)
{
if (SaveAppointment != null)
{
SaveAppointment(this, EventArgs.Empty);
}
}
private void btnNew_Click(object sender, EventArgs e)
{
if (NewAppointment != null)
{
NewAppointment(this, EventArgs.Empty);
}
}
private void btnPrevious_Click(object sender, EventArgs e)
{
if (PreviousAppointment != null)
{
PreviousAppointment(this, EventArgs.Empty);
}
}
private void btnNext_Click(object sender, EventArgs e)
{
if (NextAppointment != null)
{
NextAppointment(this, EventArgs.Empty);
}
}
private void btnYes_Click(object sender, EventArgs e)
{
if (YesButtonClick != null)
{
YesButtonClick(this, EventArgs.Empty);
}
}
private void btnNo_Click(object sender, EventArgs e)
{
if (NoButtonClick != null)
{
NoButtonClick(this, EventArgs.Empty);
}
}
private void txtAppointment_TextChanged(object sender, EventArgs e)
{
this.isDirty = true;
}
private void cboPriority_SelectedIndexChanged(object sender, EventArgs e)
{
this.isDirty = true;
}
private void txtStartDate_TextChanged(object sender, EventArgs e)
{
this.isDirty = true;
}
private void txtDueDate_TextChanged(object sender, EventArgs e)
{
this.isDirty = true;
}
private void txtCompletionDate_TextChanged(object sender, EventArgs e)
{
this.isDirty = true;
}
private void chkCompleted_CheckedChanged(object sender, EventArgs e)
{
this.isDirty = true;
}
}
}
到目前为止形成我的搜索似乎在webforms中实现对Presenters构造函数的注入可能存在问题,并且我需要覆盖PageHandler类来解析依赖项,但是到目前为止我看过的示例有首先由View创建Presenter。我想尽可能避免这种情况,并使用单独的webform页面来实例化Model,View,Presenter并以这种方式解决依赖关系。
道歉,如果我还不清楚 - 我在MVP和ASP.net Webforms的背后都非常湿透。任何建议都会非常感激,因为我很困惑如何解决这个难题。 ; D