使用MVP,构造和依赖注入的正常顺序是什么?
通常,您为每个视图创建一个presenter,并将视图传递给构造函数上的presenter。但是如果你有:
是否有人可以显示从用户点击返回到从服务器返回的服务的正常信息流。
发布于 2008-10-10 13:09:09
下面是我要做的:
首先,我定义了这些接口:
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中的双向影响。请注意,需要使用安全强制转换...
然后,我的具体演示者是这样的:
public class MyPresenter : AbstractPresenter<IMyView, MyPresenter>
{
//...
}
其中IMyView
实现了IView
。必须存在一个具体的视图类型(例如MyView
),但它是解析它的容器:
MyPresenter
类型注册为自身。MyView
注册为IMyView
。然后,MyPresenter
MyPresenter
AbstractPresenter.View
property.但在你描述的场景中,我建议你将服务和缓存注入到presenter中,而不是视图中。
发布于 2009-05-10 17:55:10
在WinForms中,我更喜欢一种简单的方法。通常,您要在设计图面上处理几个UserControls --将这些类作为视图类。.NET (通过InitializeComponent)为您创建控件层次结构。如果使用Passive View模式,则每个视图都会实例化它的presenter。(您可以直接执行此操作,也可以通过请求IOC容器来执行此操作。)使用构造函数注入将对视图接口的引用传递给演示者的构造函数。然后,演示者可以将自己连接起来以查看事件。对模型重复此过程: presenter实例化模型并连接到其事件。(在这种情况下,您不需要构造函数注入,因为被动视图表示presenter保留对模型的引用,而不是相反。)
我发现这种方法唯一的缺点是正确地管理模型和presenter的生命周期。您希望使视图尽可能简单,因此您可能不希望它维护对演示者的引用。然而,这意味着您已经将这个presenter对象与绑定到您的视图的事件处理程序挂起。此设置防止您的视图被垃圾收集。一种解决方案是让你的视图发布一个事件,表明它正在关闭。演示者将收到事件并删除其模型和视图订阅。web中的对象现在被正确地解除了引用,垃圾收集器可以继续它的工作。
你最终会得到类似下面这样的结果:
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;
}
}
通过使用IOC并向IOC容器请求IModel (在Presenter类中)和IPresenter (在View类中)的实现,您可以进一步解耦此示例。
发布于 2012-03-29 07:18:54
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;
}
}
}
https://stackoverflow.com/questions/189121
复制相似问题