使用MVP,构建和依赖注入的正常顺序是什么。
通常为每个视图创建一个Presenter,并在构造函数中将视图传递给Presenter。但如果你有以下情况:
- 多个视图需要监听Service上的事件。
- 多个视图都指向同一数据模型缓存。
能否展示一个从用户点击到从服务器返回数据的正常信息流程。
这是我的工作内容:
首先,我定义了这些接口:
public interface IView<TPresenter>
{
TPresenter Presenter { get; set; }
}
public interface IPresenter<TView, TPresenter>
where TView : IView<TPresenter>
where TPresenter : IPresenter<TView, TPresenter>
{
TView View { get; set; }
}
那么这个抽象的Presenter类:
public abstract class AbstractPresenter<TView, TPresenter> : IPresenter<TView, TPresenter>
where TView : IView<TPresenter>
where TPresenter : class, IPresenter<TView, TPresenter>
{
protected TView view;
public TView View
{
get { return this.view; }
set
{
this.view = value;
this.view.Presenter = this as TPresenter;
}
}
}
为了在setter中实现双向影响,视图是通过属性而不是构造函数注入的。请注意需要进行安全转换...
然后,我的具体Presenter类大致如下:
public class MyPresenter : AbstractPresenter<IMyView, MyPresenter>
{
//...
}
IMyView
实现 IView
。必须存在一个具体的视图类型(如 MyView
),但是容器会解析它:
MyPresenter
类型注册为自己,使用短暂行为。MyView
注册为 IMyView
,使用短暂行为。MyPresenter
。MyPresenter
。AbstractPresenter.View
属性将视图注入到演示文稿中。这使您可以将其他依赖项(服务、repos)注入到视图和演示文稿中。 但在您描述的场景中,我建议您将服务和缓存注入到 演示文稿 中,而不是视图。
public interface IView
{
...
event Action SomeEvent;
event EventHandler Disposed;
...
}
// Note that the IView.Disposed event is implemented by the
// UserControl.Disposed event.
public class View : UserControl, IView
{
public event Action SomeEvent;
public View()
{
var presenter = new Presenter(this);
}
}
public interface IModel
{
...
event Action ModelChanged;
...
}
public class Model : IModel
{
...
public event Action ModelChanged;
...
}
public class Presenter
{
private IView MyView;
private IModel MyModel;
public Presenter(View view)
{
MyView = view;
MyView.SomeEvent += RespondToSomeEvent;
MyView.Disposed += ViewDisposed;
MyModel = new Model();
MyModel.ModelChanged += RespondToModelChanged;
}
// You could take this a step further by implementing IDisposable on the
// presenter and having View.Dispose() trigger Presenter.Dispose().
private void ViewDisposed(object sender, EventArgs e)
{
MyView.SomeEvent -= RespondToSomeEvent;
MyView.Disposed -= ViewDisposed;
MyView = null;
MyModel.Modelchanged -= RespondToModelChanged;
MyModel = null;
}
}
interface IEmployee
{
int EmployeeId {get;}
string FirstName {get;}
string LastName {get;}
}
interface IEmployeeRepository
{
void SaveEmployee(IEmployee employee);
IEmployee GetEmployeeById(int employeeId);
IEmployee[] Employees { get; }
}
interface IEmployeeView
{
event Action<IEmployee> OnEmployeeSaved;
}
interface IEmployeeController
{
IEmployeeView View {get;}
IEmployeeRepository Repository {get;}
IEmployee[] Employees {get;}
}
partial class EmployeeView: UserControl, IEmployeeView
{
public EmployeeView()
{
InitComponent();
}
}
class EmployeeController:IEmployeeController
{
private IEmployeeView view;
private IEmployeeRepository repository;
public EmployeeController(IEmployeeView view, IEmployeeRepository repository)
{
this.repository = repository;
this.view = view;
this.view.OnEmployeeSaved+=new Action<IEmployee>(view_OnEmployeeSaved);
}
void view_OnEmployeeSaved(IEmployee employee)
{
repository.SaveEmployee(employee);
}
public IEmployeeView View
{
get
{
return view;
}
}
public IEmployeeRepository Repository
{
get
{
return repository;
}
}
public IEmployee[] Employees
{
get
{
return repository.Employees;
}
}
}