20170807-20170813C#工作學習周總結

win32程序開發流程

windows程序分爲“程序代碼”和“UI”資源兩大部分,兩大部分最後以RC編譯器整合爲一個完整的exe檔案。

需要什麼函數庫(.LIB)

動態鏈接庫:引用程序所調用的windows API函數是在“執行時期”才鏈接上的。

並不是擴展名是dll的纔是動態鏈接庫,事實上.exe,.dll,.fon,.mod,.drv,.ocx都是所謂的動態鏈接庫。

需要什麼頭文件

以消息爲基礎,以事件驅動之

接受並處理消息的主角就是窗口。每一個窗口都應該有一個函數負責處理消息,程序員必須負責設計這個所謂的“窗口函數”。程序員必須負責設計這個所謂的“窗口函數”。如果窗口獲得一個消息,則這個窗口函數必須判斷消息的類別,決定處理的方式。

程序進入點WinMain

當Windows的外殼shell偵測到使用者欲執行一個Windows程序,於是調用加載器把該程序加載,然後調用C startup code,後者再調用WinMain,開始執行程序。WinMain的四個參數由操作系統傳遞進來。

回調函數(什麼是回調函數)

你到一個商店買東西,剛好你要的東西沒有貨,於是你在店員那裏留下了你的電話,過了幾天店裏有貨了,店員就打了你的電話,然後你接到電話後就到店裏去取了貨。在這個例子裏,你的電話號碼就叫回調函數,你把電話留給店員就叫登記回調函數,店裏後來有貨了叫做觸發了回調關聯的事件,店員給你打電話叫做調用回調函數,你到店裏去取貨叫做響應回調事件。(作者:常溪玲鏈接:https://www.zhihu.com/question/19801131/answer/13005983來源:知乎著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。)

對話框的運行

Windows的對話框依其與父窗口的關係,可分爲兩類:

  1. “令其父窗口失效,直到對話框結束”,這種稱爲modal對話框;
  2. “父窗口與對話框共同運行”,這種稱爲modeless對話框。

資源描述文件

RC文件是一個以文字描述資源的地方

SDK程序

指以Windows raw API完成的程序

核心對象

核心對象是系統的一種資源,系用對象一旦產生,任何應用程序都可以開啓並使用該對象,系統給予核心對象一個計數值作爲管理之用。核心對象包括:event,mutex,semaphore,file,file-mapping,process,thread

虛函數

從操作型定義來看,什麼是虛函數?如果你預期派生類有可能重新定義某一個成員函數,那麼你就在基類中把此函數設爲virtual。MFC有兩個十分重要的虛函數:與document有關的Serialize函數和與view有關的OnDraw函數。應該在自己的CMyDoc和CMyView中改寫這兩個虛函數。

純虛擬函數不需定義其實際動作,它的存在只是爲了在衍生類別中被重新定義,只是爲了提供一個多態接口。只要是擁有純虛擬函數的類別,就是一種抽象類別,它是不能夠被具象化(instantiate)的,也就是說,你不能根據它產生一個對象(你怎能說一種形狀爲’Shape’ 的物體呢)。

■ 如果你期望衍生類別重新定義一個成員函數,那麼你應該在基礎類別中把此函數設爲virtual。

■ 以單一指令喚起不同函數,這種性質稱爲Polymorphism,意思是” the ability to assume many forms “,也就是多態。

■ 虛擬函數是C++ 語言的Polymorphism性質以及動態綁定的關鍵。

■ 既然抽象類別中的虛擬函數不打算被調用,我們就不應該定義它,應該把它設爲純虛擬函數(在函數聲明之後加上” =0” 即可)。

■ 我們可以說,擁有純虛擬函數者爲抽象類別(abstract Class ),以別於所謂的具象類別(concrete class ) 。

■ 抽象類別不能產生出對象實體,但是我們可以擁有指向抽象類別之指針,以便於操作抽象類別的各個衍生類別。

■ 虛擬函數衍生下去仍爲虛擬函數,而且可以省略virtual關鍵詞。

多態

編譯器無法在編譯時期判斷pEmp -> computePay到底是調用哪一個函數,必須在執行時期才能評估之,這稱爲後期綁定late binding 或動態綁定dynamic binding。

C++ Template Functions

函數聲明:

template <class T> T power (T base,int exponent);

T power(T base,int exponent);

容易讓人迷惑的是其中的”class”字眼,它其實並不一定表示C++的class,它也可以是一個普通的數據類型。不過是表示:T是一種普通類型,而此一類型將在調用此函數時纔給予。

構造式和析構式

所謂構造式(constructor),就是對象誕生後第一個執行(並且是自動執行)的函數,它的函數名稱必定要與類別名稱相同。

相對於構造式,自然就有個析構式(destructor),也就是在對象行將毀滅但未毀滅之前一刻,最後執行(並且是自動執行)的函數,它的函數名稱必定要與類別名稱相同,再在最前面加一個~ 符號。

一個有着階層架構的類別羣組,當衍生類別的對象誕生之時,構造式的執行是由最基礎類別(most based)至最尾端衍生類別(most derived);當對象要毀滅之前,析構式的執行則是反其道而行。

RTTI運行類型識別

具備IsKindOf的能力,能在執行期偵測某個對象是否“屬於某種類”,並傳回True或False。

消息映射(Message Mapping)

將消息與表格(消息映射表——Message Map)中的元素比較,然後調用對應的處理程序,這種操作我們也稱爲消息映射。

XML文件的C#讀取

在程序中訪問進而操作XML文件一般有兩種模型,分別是使用DOM(文檔對象模型)和流模型,使用DOM的好處在於它允許編輯和更新XML文檔,可以隨機訪問文檔中的數據,可以使用XPath查詢,但是,DOM的缺點在於它需要一次性的加載整個文檔到內存中,對於大型的文檔,這會造成資源問題。流模型很好的解決了這個問題,因爲它對XML文件的訪問採用的是流的概念,也就是說,任何時候在內存中只有當前節點,但它也有它的不足,它是隻讀的,僅向前的,不能在文檔中執行向後導航操作。

使用XmlDocument是一種基於文檔結構模型的方式來讀取XML文件.在XML文件中,我們可以把XML看作是由文檔聲明(Declare),元素(Element),屬性(Attribute),文本(Text)等構成的一個樹.最開始的一個結點叫作根結點,每個結點都可以有自己的子結點.得到一個結點後,可以通過一系列屬性或方法得到這個結點的值或其它的一些屬性.

   1: xn 代表一個結點
   2: xn.Name;//這個結點的名稱
   3: xn.Value;//這個結點的值
   4: xn.ChildNodes;//這個結點的所有子結點
   5: xn.ParentNode;//這個結點的父結點

1.1 讀取所有的數據.

使用的時候,首先聲明一個XmlDocument對象,然後調用Load方法,從指定的路徑加載XML文件.

   1: XmlDocument doc = new XmlDocument();
   2: doc.Load(@"..\..\Book.xml");

然後可以通過調用SelectSingleNode得到指定的結點,通過GetAttribute得到具體的屬性值.參看下面的代碼

// 得到根節點bookstore
XmlNode xn = xmlDoc.SelectSingleNode("bookstore");
// 得到根節點的所有子節點
XmlNodeList xnl = xn.ChildNodes;
foreach (XmlNode xn1 in xnl)
{
BookModel bookModel = new BookModel();
// 將節點轉換爲元素,便於得到節點的屬性值
XmlElement xe = (XmlElement)xn1;
// 得到Type和ISBN兩個屬性的屬性值
bookModel.BookISBN = xe.GetAttribute("ISBN").ToString();
bookModel.BookType = xe.GetAttribute("Type").ToString();
// 得到Book節點的所有子節點
XmlNodeList xnl0 = xe.ChildNodes;
bookModel.BookName=xnl0.Item(0).InnerText;
bookModel.BookAuthor=xnl0.Item(1).InnerText;
bookModel.BookPrice=Convert.ToDouble(xnl0.Item(2).InnerText);
bookModeList.Add(bookModel);
}
 dgvBookInfo.DataSource = bookModeList;

在正常情況下,上面的代碼好像沒有什麼問題,但是對於讀取上面的XML文件,則會出錯,原因就是因爲我上面的XML文件裏面有註釋,大家可以參看Book.xml文件中的第三行,我隨便加的一句註釋.註釋也是一種結點類型,在沒有特別說明的情況下,會默認它也是一個結點(Node).所以在把結點轉換成元素的時候就會報錯.”無法將類型爲“System.Xml.XmlComment”的對象強制轉換爲類型“System.Xml.XmlElement”。”

幸虧它裏面自帶了解決辦法,那就是在讀取的時候,告訴編譯器讓它忽略掉裏面的註釋信息.修改如下:

XmlDocument xmlDoc = new XmlDocument();
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreComments = true;//忽略文檔裏面的註釋
XmlReader reader = XmlReader.Create(@"..\..\Book.xml", settings);
xmlDoc.Load(reader);

最後讀取完畢後,記得要關掉reader.

   1: reader.Close();

這樣它就不會出現錯誤.

1.2C#讀取XML中元素和屬性的值(XmlDocument讀取Xml)

反射

什麼是反射:
1.在程序運行時,
​ 動態獲取 加載程序集
​ 動態獲取 類型(類,接口)
​ 動態獲取 類型的成員 信息(字段,屬性,方法)
2.在運行時,
​ 動態創建類型實例,以及調用和訪問這些實例成員

程序集

程序集是代碼進行編譯是的一個邏輯單元,把相關的代碼和類型進行組合,然後生成PE文件(例如可執行文件.exe和類庫文件.dll)。由於程序集在編譯後並不一定會生成單個文件,而可能會生成多個物理文件,甚至可能會生成分佈在不同位置的多個物理文件,所以程序集是一個邏輯單元,而不是一個物理單元。即程序集在邏輯上是一個編譯單元,但在物理儲存上可以有多種存在形式。對於靜態程序集可以生成單個或多個文件,而動態程序集是存在於內存中的。在C#中程序集處處可見,因爲任何基於.NET的代碼在編譯時都至少存在一個程序集(所有.NET項目都會默認引用mscorlib程序集)

類庫編譯成程序集
bin目錄下生成.dll或。.exe

程序集包含哪些內容:

類型元數據【以二進制的形式,描述代碼中定義的每一個類型和成員】
程序集元數據【程序集清單,版本號,名稱等】
IL代碼【這些都被裝在exe或dll中】
資源文件

反射中要用到動態鏈接庫作爲插件,需要聲明一個程序集來接收。

Type類

反射中用到的最重要的一種類型就是type類,System.Type類對於反射起着核心的作用。當反射請求加載的類型時,公共語言運行庫將爲它創建一個 Type。可以使用Type 對象的方法、字段、屬性和嵌套類來查找有關該類型的所有信息。

接口

爲了規範插件的行爲,需要主程序開發者編寫接口,統一操作類型及對象。

加載程序集常用到的方法示例:

        private void LoadPlugins()
        {
            // 1.加載plugins目錄下的所有的dll文件
            string plugins = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "plugins");
            //   1.1 搜索plugins目錄下的所有的dll文件 
            string[] dlls = Directory.GetFiles(plugins, "*.dll");
            // 2.循環將每個dll文件都加載起來
            foreach (string dllPath in dlls)
            {
                //  2.1 動態加載當前循環的dll文件
                Assembly assembly = Assembly.LoadFile(dllPath);
                //  2.2 獲取當前dll中的所有的public類型
                Type[] types = assembly.GetExportedTypes();
                //  2.3 獲取IEditor接口的Type
                Type typeIEditor = typeof(IEditor);

                for (int i = 0; i < types.Length; i++)
                {
                    // 2.4 驗證當前的類型即實現了IEditor接口並且該類型還可以被實例化
                    if (typeIEditor.IsAssignableFrom(types[i]) && !types[i].IsAbstract)
                    {
                        IEditor editor = (IEditor) Activator.CreateInstance(types[i]);
                        // 2.5 向菜單欄中動態添加一個菜單項
                        ToolStripItem toolItem = 編輯ToolStripMenuItem.DropDownItems.Add(editor.PluginName);
                        // 2.6 爲剛剛增加的菜單項註冊一個單擊事件
                        toolItem.Click += new EventHandler(toolItem_Click);
                        toolItem.Tag = editor;
                    }
                }
            }
        }

        private void toolItem_Click(object sender, EventArgs e)
        {
            ToolStripItem item = sender as ToolStripItem;
            if (item != null)
            {
                if (item.Tag != null)
                {
                    IEditor editor = item.Tag as IEditor;
                    if (editor != null)
                    {
                        // 運行該插件
                        editor.Execute(this.textBox1);
                    }
                }
            }
        }

其中,接口代碼如下:

    public interface IEditor
    {
        string PluginName
        {
            get;
        }

        void Execute(TextBox txtbox);
    }

網上的一篇不錯的總結:

C#學習-程序集和反射

C#反射程序集

待補充…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章