首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >MVP依赖注入

MVP依赖注入
EN

Stack Overflow用户
提问于 2008-10-09 20:41:53
回答 4查看 6K关注 0票数 13

使用MVP,构造和依赖注入的正常顺序是什么?

通常,您为每个视图创建一个presenter,并将视图传递给构造函数上的presenter。但是如果你有:

  1. 多个视图需要侦听其上的事件的服务。
  2. 多个视图都指向同一数据模型缓存。

是否有人可以显示从用户点击返回到从服务器返回的服务的正常信息流。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2008-10-10 13:09:09

下面是我要做的:

首先,我定义了这些接口:

代码语言:javascript
复制
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类:

代码语言:javascript
复制
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中的双向影响。请注意,需要使用安全强制转换...

然后,我的具体演示者是这样的:

代码语言:javascript
复制
public class MyPresenter : AbstractPresenter<IMyView, MyPresenter>
{
    //...
}

其中IMyView实现了IView。必须存在一个具体的视图类型(例如MyView),但它是解析它的容器:

  1. I使用瞬态行为在容器中将MyPresenter类型注册为自身。
  2. I使用瞬态行为在容器中将MyView注册为IMyView。然后,
  3. I向container.
  4. Container请求D15它实例化一个MyPresenter
  5. It
  6. 它实例化一个MyPresenter
  7. It通过AbstractPresenter.View property.
  8. The设置器代码将视图注入到呈现器中完成双向association
  9. The容器返回的对Presenter/View

但在你描述的场景中,我建议你将服务和缓存注入到presenter中,而不是视图中。

票数 13
EN

Stack Overflow用户

发布于 2009-05-10 17:55:10

在WinForms中,我更喜欢一种简单的方法。通常,您要在设计图面上处理几个UserControls --将这些类作为视图类。.NET (通过InitializeComponent)为您创建控件层次结构。如果使用Passive View模式,则每个视图都会实例化它的presenter。(您可以直接执行此操作,也可以通过请求IOC容器来执行此操作。)使用构造函数注入将对视图接口的引用传递给演示者的构造函数。然后,演示者可以将自己连接起来以查看事件。对模型重复此过程: presenter实例化模型并连接到其事件。(在这种情况下,您不需要构造函数注入,因为被动视图表示presenter保留对模型的引用,而不是相反。)

我发现这种方法唯一的缺点是正确地管理模型和presenter的生命周期。您希望使视图尽可能简单,因此您可能不希望它维护对演示者的引用。然而,这意味着您已经将这个presenter对象与绑定到您的视图的事件处理程序挂起。此设置防止您的视图被垃圾收集。一种解决方案是让你的视图发布一个事件,表明它正在关闭。演示者将收到事件并删除其模型和视图订阅。web中的对象现在被正确地解除了引用,垃圾收集器可以继续它的工作。

你最终会得到类似下面这样的结果:

代码语言:javascript
复制
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类中)的实现,您可以进一步解耦此示例。

票数 9
EN

Stack Overflow用户

发布于 2012-03-29 07:18:54

代码语言:javascript
复制
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;
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/189121

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档