c#中winform的MVP模式的簡單實現

MVP模式是相似於MVC模式的一種設計模式,最近在作項目學習過程當中遇到,弄了好久終於有一些眉目,這是學習過程當中的一些筆記。
MVP指的是實體對象Model、視圖Viw和業務處理Presenter。MVP的做用是解耦UI渲染、業務邏輯和數據實體的關係。在普通的winform中,業務和界面是寫在一塊兒的,通常都是同一個Load或Click方法中,使View和Controller緊密聯繫。在MVP中,咱們將界面渲染放在View裏面,也就是winfrom的窗體應用類;將業務關係放在Presenter類中,這就是MVP中的業務數據類;最後的數據實體與數據庫的交互放在Model中,是三者各司其職。
通常的MVP中,咱們是在Presenter中主動使用View,也就是界面控件形態都是由Presenter去主動控制的。而創建這二者之間的聯繫,就是在Presenter中註冊View的事件,當界面發生由用戶觸發事件時,這個事件會經過View傳遞到Presenter中,並在Presenter中調用Model的數據方法,最後Presenter調用在類中引用的View的實例去改變界面形態,下面是一些方法的實現,這裏着重說明Presenter和View的關係。
首先,咱們定義View的接口類IView,裏面就一個數據實體的引用:數據庫

1 public interface IView<T>:IView
2 {
3     T Model { get; set; }
4 }
public interface IView:IView

 

接下來,定義View的下一級接口,這裏是定義視圖一些控件和事件:設計模式

1 public interface IMainForm<T> : IView<T>
2 {
3     Button TestButton { get;}    //定義MainFrom的按鈕引用
4     TextBox TestTextBox { get; }    //定義MianForm的文本框引用
5     event EventHandler ViewLoadEvent;    //定義窗體加載完畢執行事件
6     event EventHandler ButtonSubmitEvent;    //定義按鈕事件
7     void ShowSubmitDialog();    //定義自定義的事件
8 }
public interface IMainForm : IView

 

最後就是View的實現類,裏面是實現的接口方法和屬性,包含一個按鈕及一個文本框,這裏有一個繼承了的MvpForm類和PresenterBinding的特性,一會再說:ide

 1 [PresenterBinding(typeof(MainFormPresenter))]
 2 public partial class MainForm : MvpForm , IMainForm<MainFormModel>
 3 {
 4     public MainForm()
 5     {
 6         InitializeComponent();
 7     }
 8 
 9     public MainFormModel Model { get; set; }
10     public TextBox TestTextBox { get { return txtText; } }
11     public Button TestButton { get { return btnSubmit; } }
12 
13     public event EventHandler ViewLoadEvent;
14     public event EventHandler ButtonSubmitEvent;
15 
16     private void MainForm_Load(object sender, EventArgs e)
17     {
18         if (ViewLoadEvent != null) ViewLoadEvent(sender, e);
19     }
20 
21     public void ShowSubmitDialog()
22     {
23         MessageBox.Show("to submit?");
24     }
25 
26     private void btnSubmit_Click(object sender, EventArgs e)
27     {
28         if (ButtonSubmitEvent != null) ButtonSubmitEvent(sender , e);
29     }
30 }
public partial class MainForm : MvpForm , IMainForm

 

定義完View的內容,就能夠看一下Presenter,一樣,先有接口,再有實現,先定義Presenter的接口:函數

1 public interface IPresenter<T>:IPresenter where T : class, View.IView
2 {
3     T View { get; }
4 }
public interface IPresenter:IPresenter where T : class, View.IView

 

這裏再定義一個Presenter的抽象類,用於統一各個不一樣View對應的Presenter類,其定義以下:學習

 1 public abstract class Presenter<T> : IPresenter<T> where T : class, View.IView
 2 {
 3     private readonly T view;
 4 
 5     //這裏的view做爲引用,用於在presenter中獲取View的實例
 6     protected Presenter(T view)
 7     {
 8     this.view = view;
 9     }
10 
11     public T View { get { return view; } }
12 }
public abstract class Presenter : IPresenter where T : class, View.IView

 

最後就是對應的View的Presenter類了:this

 1 class MainFormPresenter:Presenter<View.IMainForm<Model.MainFormModel>>
 2 {
 3     public MainFormPresenter(View.IMainForm<Model.MainFormModel> view)
 4 : base(view)
 5     {
 6     view.Model = new Model.MainFormModel();
 7 
 8     view.ViewLoadEvent += On_ViewLoad;
 9     view.ButtonSubmitEvent += On_ButtonSubmitClick;
10     init();
11     }
12 
13     public void init()
14     {
15         //To Do something...
16     }
17 
18     public void On_ViewLoad(object sender, EventArgs e)
19     {
20         //To Do something...
21     }
22 
23     public void On_ButtonSubmitClick(object sender, EventArgs e)
24     {
25         View.ShowSubmitDialog();//經過view的實例調用view的方法來改變控件形態
26     }
27 }
class MainFormPresenter:Presenter<View.IMainForm>

 

這裏定義了Presenter和View的接口和實現,下面就是如何將這兩個不一樣的模塊聯合在一塊兒,這裏,使用的是.net的特性和反射。
首先,先創建特性類PresenterBindingAttribute,經過在View的實現類標記該特性類和指定對應的Presenter類,就能夠獲取View和Presenter的對應關係了,該類一樣要標註特性AttributeUsage和繼承Attribute類,同時定義兩個屬性參數:spa

 1 [AttributeUsage(AttributeTargets.Class,AllowMultiple = true)]
 2 public sealed class PresenterBindingAttribute : Attribute
 3 {
 4     public Type PresenterType { get;private set; }
 5 
 6     public Type ViewType { get; set; }
 7 
 8     public PresenterBindingAttribute(Type presenterType)
 9     {
10         PresenterType = presenterType;
11         ViewType = null;
12     }
13 }
public sealed class PresenterBindingAttribute : Attribute

 

接下來,就是經過反射去創建view和presenter的關係,這裏創建PerformBinding類:.net

 1 public IPresenter PerformBinding(IView viewInstance)
 2 {
 3     IPresenter presenter = null;
 4     Type t = viewInstance.GetType();    //獲取該視圖的類類型
 5     object[] attrs = t.GetCustomAttributes(typeof(PresenterBindingAttribute), false);    //獲取該類上的附加特性集合
 6     //遍歷特性集合,找到Presenter類型附加的特性,經過該特性創建實例
 7     foreach (PresenterBindingAttribute pba in attrs)
 8     {
 9         Type newt = pba.PresenterType;    //獲取Presenter類類型
10         //創建Presenter實例,這裏的構造參數是View的對象,這樣就使二者創建了聯繫
11         Object obj = Activator.CreateInstance(pba.PresenterType, viewInstance);
12         presenter = obj as IPresenter;
13     }
14     return presenter;
15 }
public IPresenter PerformBinding(IView viewInstance)

 

那麼,這個類PerformBinding在哪裏使用,通常是在應用View啓動是就要註冊實例,這裏爲了解除類間的強耦合,就添加一箇中間類。在前面的View的實現類中,是繼承自一個MvpForm的類,這個MvpForm就使註冊View和Presenter關係的類,接下來看MvpForm的實現:設計

1 public partial class MvpForm : Form,IView
2 {
3     private readonly PresenterBinder presenterBinder = new PresenterBinder();
4     public MvpForm()
5     {
6         presenterBinder.PerformBinding(this);    //註冊關係
7     }
8 }
public partial class MvpForm : Form,IView

 

這樣,就創建了View與Presenter之間的關係,每次View頁面啓動,就先執行父類MvpForm的構造函數,註冊View和Presenter的關係,相應的邏輯能夠寫在Presenter中,View的做用就是做爲UI的渲染。之後添加View和Presenter實現類時,只須要繼承和實現相應的類和接口,並在View實現類添加相應的對應類特性,就可實現MVP的設計關係。3d

相關文章
相關標籤/搜索