使用MVP,構造和依賴注入的正常順序是什麼。MVP依賴注入
通常情況下,您爲每個視圖創建一個演示者,並將該視圖傳遞給構造函數上的演示者。但是如果你有:
- 多個視圖需要監聽事件的服務。
- 多個視圖都指向相同的數據模型緩存。
有人可以顯示正常的信息流從用戶點擊到數據從服務器返回服務。
使用MVP,構造和依賴注入的正常順序是什麼。MVP依賴注入
通常情況下,您爲每個視圖創建一個演示者,並將該視圖傳遞給構造函數上的演示者。但是如果你有:
有人可以顯示正常的信息流從用戶點擊到數據從服務器返回服務。
這裏是我做的:
首先,我定義論文的接口:
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; }
}
那麼這個抽象主持人類:
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
屬性注入視圖到主持人。它可以讓你注入其他依賴(服務,回購)到兩個視圖和您的主持人。但是,在您描述的情況下,我建議您將服務和緩存注入主講人,而不是視圖。
在WinForms中,我更喜歡簡單的方法。通常你在設計表面上處理幾個UserControls - 使這些視圖類成爲你的視圖類。 .NET爲您創建控件層次結構(通過InitializeComponent)。如果您使用Passive View模式,則每個視圖會實例化其演示者。 (您可以直接或通過詢問IOC容器來做到這一點。)使用構造函數注入將視圖的接口的引用傳遞給演示者的構造函數。演示者然後可以連線自己查看事件。重複模型的過程:演示者實例化一個模型並連接到它的事件。 (在這種情況下,你不需要構造函數注入,因爲被動視圖說主持人保持對模型的引用,而不是反之亦然。)
我發現這種方法唯一的缺點是正確管理模型和主持人。您希望保持視圖儘可能簡單,所以您可能不希望它保持對演示者的引用。但是,這意味着您已將此演示者對象與視圖綁定的事件處理程序掛在一起。此設置可防止您的視圖被垃圾收集。一種解決方案是讓你的視圖發佈一個事件,表明它正在關閉。演示者將收到該事件並刪除其模型和查看訂閱。您的網絡中的對象現在已正確解除引用,垃圾收集器可以繼續其工作。
你風的東西,如下列:
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;
}
}
您可以通過使用國際奧委會和要求IModel的實現您的IOC容器(在演示類)和IPresenter一步脫鉤這個例子( View類)。
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;
}
}
}
能否請您評論你的代碼? – 2012-10-28 00:14:47
你是如何處理IDisposable的顧慮嗎?特別是,打破循環引用以允許垃圾收集? – aboy021 2013-04-29 02:48:39