.Net開發筆記(十一) 設計時(Design-Time)和運行時(Run-Time)的區別


設計時和運行時的概念網上的中文資料很少,如果不是做第三方組件開發的或者跟設計器開發有關的,幾乎用不到這些概念。為了迎合之前幾篇博客,我想有必要說一下它兩的概念和區別,以及用在什么地方。博客好久沒更新,比較忙。

首先,我個人認為“設計時”和“運行時”是針對組件而言的(包括控件),也就是說,一個組件可以處在“運行時”也可以處在“設計時”兩個狀態,從字面上的意思來看,“設計時”當然是指處在開發階段,開發人員在設計器中開發組件的時候,而“運行時”指程序處在運行階段,比如一個button控件,在設計器中的窗體中時,它就處於“設計時”,當程序運行起來之后,這個button還是在窗體中,但它處於“運行時”了。呵,字面上的意思很好理解,那么這兩個狀態到底有什么用呢?也就是說,微軟為什么規定組件有兩個狀態?想要了解這個問題的答案,我們先得清楚“可視化設計器”(比如VS  IDE)的作用,簡單的總結一下:可視化設計器提供一個WYSIWYG(所見即所得)的開發環境,為開發人員提供一個更直觀的操作平台。可是,就是這么兩句簡單的話,卻迷惑了多少人。我們來看一張圖:

如圖所示,任何組件都是可以放在“設計器”中設計的(詳見前面幾篇博客),也就是說,組件具備“可視化設計”的特性,開發人員通過向設計器中添加組件,就可以快速地設計出一個類型(Form1),然后生成代碼文檔,保存。整個過程需要注意一下幾點:

  • 組件具備“可視化設計”的特性,這里的設計並不代表我們可以改變原有組件的代碼,比如向設計器中拖進一個Button控件,默認命名“button1”,接着我們編輯它的屬性、綁定事件等等,這些所有的操作都只發生在button1身上,並不會影響原來Button類代碼。換句話說,只設計“組件實例“。
  • 開發人員向設計器中添加組件(包括控件),設計器中的組件都是“實例”,也就是說圖中的label1、textbox1、button1這些東西都是實實在在地“控件實例”,什么叫“控件實例”?就是說它們都有自己的句柄(Handle)、窗口過程(WndProc)(控件即窗體,窗體即控件,窗體都有句柄和窗口過程,不清楚的請看前面的博客),如果諸位不相信,可以用Spy++查看設計器中的這些控件,可以查找出它們的Handle以及其他信息。關於這一點,我前面博客已經解釋過,這里我再提一下。
  • 不管我們怎么操作設計器,我們在設計器中看到的東西確實跟程序運行后的界面大概差不多,但是需要明白的是,設計器中的東西全部都是“虛”的,為什么說它是虛的?因為我們一關閉設計器之后,設計器中的東西全部銷毀了,而真正有用的東西就是圖中③生成的代碼文檔!對,你沒有看錯,我更沒有寫錯,代碼文檔才是我們最終需要的東西,我們可以將它編譯生成exe或者dll文件,不是嗎?
  • 接3),我們可以一句話來概括一下“設計器”的作用:為了更快的生成想要的代碼。是的,設計器最終的目的就是為開發人員快速生成代碼,換句話說,假如沒有設計器,開發人員完全可以自己去寫代碼(比如圖中的Form1.cs和Form1.Designer.cs),可是沒有哪個sb會這樣去做,因為那樣實在太麻煩了。
  • 我們將生成的代碼文檔編譯生成exe文件,運行之,我們會看見什么?毫無疑問,我們會看見與設計器中差不多類似的界面,有一個label、一個textbox、一個button。這個是為什么?因為生成的代碼都是由設計器生成的,我們拖進去一個Label,設計器就會生成類似如下的代碼:
1 Label  label1 = new Label();
2 
3 label1.Location = new Point(10,10);
4 
5 label1.Text = “label1”;
6 
7 this.Controls.Add(label1);

//大概類似這樣,可能不相同

同理,textbox1和button1也一樣。如果我們在屬性列表中修改label1的Text屬性為“test”,那么,立即有這樣的代碼生成:

label1.Text = “test”;

注意,以上自動生成的代碼都在InitializeComponent方法中,我們將生成的代碼編譯運行,當然會按照原來設計時的樣子一一還原。

如果看懂以上5點的童鞋,那么基本上就能理解本篇博客所要說明的問題了。我們再來回憶一下文章開始提出來的問題:組件為啥要有兩個狀態,設計時(Design-Time)和運行時(Run-Time)?答案在2)和5)中,已經說過,設計器中的任何組件都是實例,換句話說,你往設計器中拖放組件的時候,會調用它的構造方法,如果該組件恰好是一個控件,那么肯定會激發它的Load事件,當它在設計器中重繪時,肯定會激發它的Paint事件等等等。也就是說,如果我自定義一個控件:

1 MyControl:UserControl
2 {
3 protected override OnLoad(EventArgs e)
4 {
5      MessageBox(“加載了!”);
6 }
7 }
View Code

本來設計這個自定義控件的開發人員想讓控件加載時,彈出一個消息框,現在問題來了,使用這個自定義控件的coder,只要將該控件拖進設計器時,就會彈出一個MessageBox,毫無疑問,這不是我們希望的。如下圖:

這只是一個簡單例子,如果我們在開發第三方組建時,需要在某些場合進行IO操作、訪問數據庫或者操作注冊表等等,那么就有必要考慮這些會不會在設計器中發生,比如修改一下上面的代碼:

1 MyControl:UserControl
2 {
3 protected override OnLoad(EventArgs e)
4 {
5      //操作注冊表
6      //連接數據庫
7 }
8 }
View Code

問題就顯而易見了,只要你將該控件拖進設計器,那么就會發生“操作注冊表”或者“連接數據庫”這樣的行為。

想要解決以上問題,微軟就提出來了“設計時”和“運行時”的概念,其實就我個人理解,同一個組件,它出現在設計器中,它就是處於“設計時”,否則它就是處於“運行時”,每個組件都有一個DesinMode屬性,如果該屬性為true,那么它就是處於“設計時”,否則,它就是處於“運行時”。(注:該方法判斷不太准確,只適合大部分場合,使用所有場合的判斷方法現在不必提及

那么,原有代碼就可以修改為:

 1 MyControl:UserControl
 2 {
 3 protected override OnLoad(EventArgs e)
 4 {
 5 if(!DesignMode)  //如果不處於“設計時”
 6 {
 7        //操作注冊表
 8        //連接數據庫
 9     }
10 }
11 }
View Code

問題完美解決。設計時和運行時的概念,就像同一個人,出生在官宦之家,那么他就是“官二代”,如果出生在普通家庭,那么他很有可能是所謂的“屌絲”。官二代和屌絲有很大的區別,就像設計器中的Button和運行期間的Button,差別很大。

另外,至於為什么設計器中的組件與運行時的組件能有不同的表現,比如設計器中的組件可以通過屬性列表編輯它的屬性,可以改變它的位置、大小等等等等,甚至為什么會自動生成代碼,這些東西都屬於設計器所必須具備的功能,本篇文章不討論。

代碼為word中所寫,如有錯誤,望見諒!希望對諸位有幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM