亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

<展現C#> 第八章 用C#寫組件

2019-11-18 22:06:49
字體:
來源:轉載
供稿:網友
第八章    用C#寫組件

    這一章關于用C#寫組件。你學到如何寫一個組件,如何編譯它,且如何在一個客戶程序中使用它。更深入一步是運用名字空間來組織你的應用程序。
    這章由兩個主要大節構成:
    。你的第一個組件
    。使用名字空間工作

8.1  你的第一個組件
    到目前為止,在本書中提到的例子都是在同一個應用程序中直接使用一個類。類和它的使用者被包含在同一個執行文件中?,F在我們將把類和使用者分離到組件和客戶,它們分別位于不同的二進制文件中(可執行文件)。
    盡管你仍然為組件創建一個 DLL,但其步驟與用C++寫一個COM組件差別很大。你很少涉及到底層結構。以下小節說明了如何構建一個組件以及使用到它的客戶:

    。構建組件
    。編譯組件
    。創建一個簡單的客戶應用程序

8.1.1  構建組件
    因為我是一個使用范例迷,我決定創建一個相關Web的類,以方便你們使用。它返回一個Web網頁并儲存在一個字符串
變量中,以供后來重用。所有這些編寫都參考了.NET框架的幫助文檔。
    類名為RequestWebPage;它有兩個構造函數——  一個屬性和一個方法。屬性被命名為URL,且它儲存了網頁的Web地
址,由方法GetContent返回。這個方法為你做了所有的工作(見清單8.1)。

    清單 8.1   用于從Web服務器返回HTML網頁的RequestWebPage 類

1: using System;
2: using System.Net;
3: using System.IO;
4: using System.Text;
5:
6: public class RequestWebPage
7: {
8:  PRivate const int BUFFER_SIZE = 128;
9:  private string m_strURL;
10:
11:  public RequestWebPage()
12:  {
13:  }
14:
15:  public RequestWebPage(string strURL)
16:  {
17:   m_strURL = strURL;
18:  }
19:
20:  public string URL
21:  {
22:   get { return m_strURL; }
23:   set { m_strURL = value; }
24:  }
25:  public void GetContent(out string strContent)
26:  {
27:   // 檢查 URL
28:   if (m_strURL == "")
29:    throw new ArgumentException("URL must be provided.");
30:
31:  WebRequest theRequest = (WebRequest) WebRequestFactory.Create(m_strURL);
32:   WebResponse theResponse = theRequest.GetResponse();
33:
34:   // 給回應設置字節緩沖區
35:   int BytesRead = 0;
36:   Byte[] Buffer = new Byte[BUFFER_SIZE];
37:
38:   Stream ResponseStream = theResponse.GetResponseStream();
39:   BytesRead = ResponseStream.Read(Buffer, 0, BUFFER_SIZE);
40:
41:   //使用 StringBuilder  以加速分配過程
42:   StringBuilder strResponse = new StringBuilder("");
43:   while (BytesRead != 0 )
44:   {
45:    strResponse.Append(Encoding.ASCII.GetString(Buffer,0,BytesRead));
46:    BytesRead = ResponseStream.Read(Buffer, 0, BUFFER_SIZE);
47:   }
48:
49:   // 賦給輸出參數
50:   strContent = strResponse.ToString();
51:  }
52: }

    本應該利用無參數構造函數完成工作,但我決定在構造函數中初始化URL,這可能會很有用。當后來決定要改變URL
時——為了返回第二個網頁,例如,通過URL屬性的get和set訪問標志使它被公開了。
    有趣的事始于GetContent方法。首先,代碼對URL實行十分簡單的檢查,如果它不適合,就會引發一個
ArgumentException 異常。之后,我請求WebRequestFactory ,以創建一個基于傳遞給它的URL的WebRequest對象。
    因為我不想發送cookies、附加頭和詢問串等,所以立即訪問WebResponse(第32行)。如果你需要請求上述任何的功
能,必須在這一行之前實現它們。
    第35和36行初始化一個字節緩沖區,它用于從返回流中讀數據。暫時忽略StringBuilder 類,只要返回流中仍然有要
讀的數據,while循環就會簡單地重復。最后的讀操作將返回零,因此結束了該循環。
    現在我想回到StringBuilder類。為什么用這個類的實例而不是簡單地把字節緩沖區合并到一個字符串變量?看下面這
個例子:
    strMyString = strMyString + "some more text";
    這里很清楚,你正在拷貝值。常量 "some more text" 以一個字符串變量類型被加框,且根據加法操作創建了一個新
的字符串變量。接著被賦給了 strMyString。有很多次拷貝,是嗎?
    但你可能引起爭論
    strMyString += "some more text";
    不要炫耀這種行為。對不起,對于C#這是一個錯誤的答案。其操作完全與所描述的賦值操作相同。
    不涉及該問題的另外的途徑是使用StringBuilder類。它利用一個緩沖區進行工作,接著,在沒有發生我所描述的拷貝
行為的情況下,你進行追加、插入、刪除和替換操作。這就是為什么我在類中使用它來合并那些讀自緩沖區中的內容。
    該緩沖區把我帶進了這個類中最后重要的代碼片段——第45行的編碼轉換。它只不過涉及到我獲得請求的字符集。
    最后,當所有的內容被讀入且被轉換時,我顯式地從 StringBuilder請求一個字符串對象并把它賦給了輸出變量。一
個返回值仍然會導致另外的拷貝操作。

8.1.2  編譯組件
    到目前為止,你所做的工作與在正常應用程序的內部編寫一個類沒有什么區別。所不同的是編譯過程。你必須創建一
個庫而不是一個應用程序:
    csc /r:System.Net.dll /t:library /out:wrq.dll webrequest.cs
    編譯開關/t:library  告訴C#編譯,要創建一個庫而不是搜尋一個靜態 Main方法。同樣,因為我正在使用
System.Net名字空間,所以必須引用 (/r:)它的庫,這個庫就是System.Net.dll。
    你的庫命名為 wrq.dll,現在它準備用于一個客戶應用程序。因為在這章中我僅使用私有組件工作,所以你不必把庫
拷貝到一個特殊的位置,而是拷貝到客戶應用程序目錄。

8.1.3  創建一個簡單的客戶應用程序
    當一個組件被寫成且被成功地編譯時,你所要做的就是在客戶應用程序中使用它。我再次創建了一個簡單的命令行應
用程序,它返回了我維護的一個開發站點的首頁(見清單8.2)。

    清單 8.2    用 RequestWebPage 類返回一個簡單的網頁

1: using System;
2:
3: class TestWebReq
4: {
5:  public static void Main()
6:  {
7:   RequestWebPage wrq = new RequestWebPage();
8:   wrq.URL = "http://www.alphasierrapapa.com/iisdev/";
9:
10:   string strResult;
11:   try
12:   {
13:    wrq.GetContent(out strResult);
14:   }
15:   catch (Exception e)
16:   {
17:    Console.WriteLine(e);
18:    return;
19:   }
20:
21:   Console.WriteLine(strResult);
22:  }
成員
    
    注意,我已經在一個try catch語句中包含了對 GetContent的調用。其中的一個原因是GetContent可能引發一個
ArgumentException異常。此外,我在組件內部調用的.NET框架類也可以引發異常。因為我不能在類的內部處理這些異常,
所以我必須在這里處理它們。
    其余的代碼只不過是簡單的組件使用——調用標準的構造函數,存取一個屬性,并執行一個方法。但等一下:你需要
注意何時編譯應用程序。一定要告訴編譯器,讓它引用你的新組件庫DLL:
    csc /r:wrq.dll wrclient.cs
    現在萬事俱備,你可以測試程序了。輸出結果會滾屏,但你可以看到應用程序工作。使用了常規的表達式,你也可以
增加代碼,以解析返回的HTML,并依據你個人的喜好,提取信息。我預想會使用到這個類新版本的SSL(安全套接字層),
用于asp+網頁中的在線信用卡驗證。
    你可能會注意到,沒有特殊的using 語句用于你所創建的庫。原因是你在組件的源文件中沒有定義名字空間。

8.2  使用名字空間工作
    你經常使用到名字空間,例如System 和System.Net。C#利用名字空間來組織程序,而且分層的組織使一個程序的成員
傳到另一個程序變得更容易。
    盡管不強制,但你總要創建名字空間,以清楚地識別應用程序的層次。.NET框架會給出構建這種分層的良好思想。
    以下的代碼片段顯示了在C#原文件中簡單的名字空間 My.Test(點號表示一個分層等級)的聲明:

namespace My.Test
{
  //這里的任何東西屬于名字空間
}

    當你訪問名字空間中的一個成員時,也有必要使用名字空間標識符完全地驗證它,或者利用using標志把所有的成員引
入到你當前的名字空間。本書前面的例子演示了如何應用這些技術。
    在開始使用名字空間之前,只有少數有關存取安全的詞。如果你不增加一個特定的存取修飾符,所有的類型將被默認
為internal 。當你想從外部訪問該類型時,使用 public 。不允許其它的修飾符。
    這是關于名字空間充分的理論。讓我們繼續實現該理論——以下小節說明了當構建組件應用程序時,如何使用名字空

    。在名字空間中包裝類
    。在客戶應用程序中使用名字空間
    。為名字空間增加多個類

8.2.1  在名字空間中包裝類
    既然你知道了名字空間的理論含義,那么讓我們在現實生活中實現它吧。在這個和即將討論到的例子中,自然選擇到
的名字空間是Presenting.CSharp。為了不使你厭煩,僅僅是把RequestWebPage包裝到Presenting.CSharp中,我決定寫一
個類,用于 Whois查找(見清單8.3)。

    清單 8.3   在名字空間中實現 WhoisLookup類

1: using System;
2: using System.Net.Sockets;
3: using System.IO;
4: using System.Text;
5:
6: namespace Presenting.CSharp
7: {
8: public class WhoisLookup
9: {
10:  public static bool Query(string strDomain, out string strWhoisInfo)
11:  {
12:   const int BUFFER_SIZE = 128;
13:
14:   if ("" == strDomain)
15:    throw new ArgumentException("You must specify a domain name.");
16:
17:   TCPClient tcpc = new TCPClient();
18:   strWhoisInfo = "N/A";
19:
20:   // 企圖連接 whois  服務器
21:   if (tcpc.Connect("whois.networksolutions.com", 43) != 0)
22:     return false;
23:         
24:   // 獲取流
25:   Stream s = tcpc.GetStream();
26:
27:   // 發送請求
28:   strDomain += "/r/n";
29:   Byte[] bDomArr = Encoding.ASCII.GetBytes(strDomain.ToCharArray());
30:   s.Write(bDomArr, 0, strDomain.Length);   
31:      
32:   Byte[] Buffer = new Byte[BUFFER_SIZE];
33:   StringBuilder strWhoisResponse = new StringBuilder("");
34:
35:   int BytesRead = s.Read(Buffer, 0, BUFFER_SIZE);
36:   while (BytesRead != 0 )
37:   {
38:   strWhoisResponse.Append(Encoding.ASCII.GetString(Buffer,0,BytesRead));
39:   BytesRead = s.Read(Buffer, 0, BUFFER_SIZE);
40:   }
41:
42:   tcpc.Close();
43:   strWhoisInfo = strWhoisResponse.ToString();
44:   return true;
45:  }
46: }
47: }

    名字空間在第6行被聲明,而且它用第7行和第47行的大括弧括住了WhoisLookup類。要聲明自己新的名字空間,實際要
做的就是這些。
    在WhoisLookup類中當然具有一些有趣代碼,特別是由于它說明了使用C#進行socket編程是多么的容易。在static
Query method中經過 not-so-stellar域名檢查之后,我實例化了TCPClient類型的一個對象,它用來完成具有 Whois服務
器的43端口上的所有通訊。在第21行建立了服務器連接:
    if (tcpc.Connect("whois.networksolutions.com", 43) != 0)
    因為連接失敗是預料到的結果,所以這個方法不能引發一個異常。(你還記住異常處理的“要”和“不要”嗎?) 返
回值是一個錯誤代碼,而返回零則說明連接成功。
    對于 Whois 查找,我必須首先發出一些信息給服務器——我要查找的域名。要完成此項工作,首先獲得一個引用給當
前TCP連接的雙向流(第25行)。接著附加上一個回車/換行對 給域名,以表示詢問結束。重新以字節數組打包,向Whois
服務器發送一個請求(第30行)。
    余下的代碼和RequestWebPage類極其相似。在該類中,我再次利用一個緩沖區從遠程服務器讀入回應。當緩沖區完成
讀入后,連接被斷開。返回的回應被轉給了調用者。我明確地調用 Close 方法的原因是我不想等待垃圾收集器毀壞連接。
連接時間不要過長,以免占用TCP端口這種稀有資源。
    在可以使用.NET 組件中的類之前,你必須把它作為一個庫來編譯。盡管現在有了一個已定義的名字空間,該編譯命令
仍然沒有變:
    csc /r:System.Net.dll /t:library /out:whois.dll whois.cs
    注意,如果你想該庫按與C#源文件相同的方法命名,就沒有必要規定 /out:開關。規定該開關是一個良好的習慣,因
為很多項目不會只由單個源文件組成。如果你規定了多個源文件,該庫以名單中的第一個命名。

8.2.2  在客戶應用程序中使用名字空間
    由于你使用了名字空間開發組件,所以客戶也要引入名字空間
    using Presenting.CSharp;
    或者給名字空間中的成員使用完全資格名(fully  qualified name),例如
    Presenting.CSharp.WhoisLookup.Query(...);

    如果你不期望在名字空間中引入的成員之間出現沖突,using  標志( directive)是首選,特別是由于你具有很少的
類型時。使用組件的客戶程序樣本在清單8.4中給出。

    清單  8.4  測試 WhoisLookup     組件

1: using System;
2: using Presenting.CSharp;
3:
4: class TestWhois
5: {
6:  public static void Main()
7:  {
8:   string strResult;
9:   bool bReturnValue;
10:
11:   try
12:   {
13:    bReturnValue = WhoisLookup.Query("microsoft.com", out strResult);
14:   }
15:   catch (Exception e)
16:   {
17:    Console.WriteLine(e);
18:    return;
19:   }
20:   if (bReturnValue)
21:    Console.WriteLine(strResult);
22:   else
23:    Console.WriteLine("Could not obtain information from server.");
24:  }
25: }

    第2行利用using 標志引入了Presenting.CSharp名字空間?,F在,我無論什么時候引用WhoisLookup ,都可以忽略名
字空間的完全資格名了。
    該程序對 microsoft.com 域進行一次Whois 查找——你也可以用自己的域名代替microsoft.com 。允許命令行參數傳
遞域名,可使客戶的用途更廣。清單8.5 實現了該功能,但它不能實現適當的異常處理(為了使程序更短)。

    清單  8.5  傳遞命令行參數給Query 方法

1: using System;
2: using Presenting.CSharp;
3:
4: class WhoisShort
5: {
6:  public static void Main(string[] args)
7:  {
8:   string strResult;
9:   bool bReturnValue;
10:
11:   bReturnValue = WhoisLookup.Query(args[0], out strResult);
12:
13:   if (bReturnValue)
14:    Console.WriteLine(strResult);
15:   else
16:    Console.WriteLine("Lookup failed.");
17:  }
18: }

    你所必須做的就是編譯這個應用程序:
    csc /r:whois.dll whoisclnt.cs
    接著可以使用命令行參數執行該應用程序。例如,以 microsoft.com參數執行
    whoisclnt microsoft.com
    當查詢運行成功時,就會出現 microsoft.com的注冊信息。(清單8.6 顯示了輸出的簡略版本)  這是一個很方便的
小程序,通過組件化的途徑寫成的,花不到一個小時。如果用C++編寫,要花多長時間?很幸運,我再也想不起當第一次用
C++這樣做時,花了多長的時間。

    清單 8.6   有關 microsoft.com (簡略) 的Whois 信息
D:/CSharp/Samples/Namespace>whoisclient
...

Registrant:
Microsoft Corporation (MICROSOFT-DOM)
  1 microsoft way
  redmond, WA 98052
  US
  Domain Name: MICROSOFT.COM

  Administrative Contact:
   Microsoft Hostmaster (MH37-ORG) msnhst@MICROSOFT.COM
  Technical Contact, Zone Contact:
   MSN NOC (MN5-ORG) msnnoc@MICROSOFT.COM
  Billing Contact:
   Microsoft-Internic Billing Issues (MDB-ORG)     msnbill@MICROSOFT.COM

  Record last updated on 20-May-2000.
  Record expires on 03-May-2010.
  Record created on 02-May-1991.
  Database last updated on 9-Jun-2000 13:50:52 EDT.

  Domain servers in listed order:

  ATBD.MICROSOFT.COM      131.107.1.7
  DNS1.MICROSOFT.COM      131.107.1.240
  DNS4.CP.MSFT.NET       207.46.138.11
  DNS5.CP.MSFT.NET       207.46.138.12

8.2.3  增加多個類到名字空間
    使WhoisLookup和RequestWebPage 類共存于同一個名字空間是多么的美妙。既然WhoisLookup已是名字空間的一部分,
所以你只須使RequestWebPage 類也成為該名字空間的一部分。
    必要的改變很容易被應用。你只需使用名字空間封裝RequestWebPage 類就可以了:

namespace Presenting.CSharp
{
public class RequestWebPage
{
...
}
}

    盡管兩個類包含于兩個不同的文件,但在編譯后,它們都是相同名字空間的一部分:
    csc /r:System.Net.dll /t:library /out:presenting.csharp.dll whois.cs webrequest.cs

    你不必要按照名字空間的名字給DLL命名。然而,這樣做會有助你更容易你記住,當編譯一個客戶應用程序時要引用哪
一個庫。
  
8.3  小結
    在這一章中,你學到了如何構建一個可以在客戶程序中使用的組件。最初,你不必關心名字空間,但后面第二個組件
中介紹了該特性。名字空間在內外部均是組織應用程序的好辦法。
    C#中的組件很容易被構建,而且只要庫和應用程序共存于相同的目錄,你甚至不必進行特殊的安裝。當要創建必須被
多個客戶使用的類庫時,步驟就有所改變——而下一章將會告訴你為什么。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本成人激情视频| 久久久久久久电影一区| 日韩大陆欧美高清视频区| 日本久久久久久久久| 欧美专区在线观看| 欧美一区视频在线| 亚洲第一综合天堂另类专| 亚洲国产福利在线| 97精品国产aⅴ7777| 亚洲色图欧美制服丝袜另类第一页| 久久久久女教师免费一区| 日本欧美在线视频| 最近2019免费中文字幕视频三| 久久久久久久久久久久av| 青青久久av北条麻妃海外网| 日韩欧美在线免费观看| 亚洲香蕉成视频在线观看| 最近2019中文免费高清视频观看www99| 久久久成人av| 欧美成人在线网站| 97色伦亚洲国产| 亚洲国内精品在线| 久久久99久久精品女同性| 麻豆乱码国产一区二区三区| 日韩在线观看免费全集电视剧网站| 夜夜嗨av色综合久久久综合网| 国产精品福利网站| 日韩av一卡二卡| 4p变态网欧美系列| 91免费版网站入口| 国产精品色婷婷视频| 亚洲精品国精品久久99热| 欧美日韩在线视频一区| 亚洲一区二区在线| 一区二区三区无码高清视频| 亚洲一区二区三区成人在线视频精品| 91丨九色丨国产在线| 国产成人免费av电影| 日韩av不卡在线| 亚洲综合色激情五月| 黄色一区二区在线| 精品久久久久久久久中文字幕| 亚洲第一在线视频| 亚洲va欧美va在线观看| 日韩电视剧免费观看网站| 亚洲风情亚aⅴ在线发布| 中文字幕亚洲一区| 久久免费福利视频| 亚洲韩国日本中文字幕| 亚洲另类欧美自拍| 热久久99这里有精品| 欧美在线视频一区二区| 亚洲精品久久久久中文字幕欢迎你| 欧美福利小视频| 51精品在线观看| 成人久久久久久| 免费91在线视频| 国自在线精品视频| 久久人人看视频| 欧美性猛交xxxx乱大交| 色阁综合伊人av| 国产成人自拍视频在线观看| 欧美激情视频给我| 亚洲天堂2020| 日韩有码在线播放| 国产丝袜精品视频| 按摩亚洲人久久| 3344国产精品免费看| 日韩av在线一区二区| 国产精品久久久久久五月尺| 欧美激情视频播放| 亚洲国产成人精品女人久久久| 成人a视频在线观看| 影音先锋日韩有码| 爽爽爽爽爽爽爽成人免费观看| 亚洲区一区二区| 青青草原成人在线视频| 国产亚洲精品综合一区91| 国产精品h片在线播放| 久久精品国产精品亚洲| 欧美在线视频观看免费网站| 韩国精品美女www爽爽爽视频| 亚洲白虎美女被爆操| 日韩欧美国产激情| 久久精品2019中文字幕| 亚洲男人天堂古典| 日本不卡视频在线播放| 国产精国产精品| 午夜精品久久久久久久99热浪潮| 久久久久久中文字幕| 91高清视频免费| 欧美日韩精品在线播放| 国产精品老女人精品视频| 国产xxx69麻豆国语对白| 精品国产乱码久久久久久天美| 成人激情在线观看| 亚洲a级在线播放观看| 一区二区三区视频在线| 亚洲国产成人91精品| 亚洲欧美综合另类中字| 国产一区红桃视频| 伊人av综合网| 日韩在线播放一区| 国产欧美一区二区三区在线看| 精品久久久久久久久久久| 欧美一级高清免费播放| 91网站免费观看| 亚洲人成在线一二| 亚洲国产天堂久久国产91| 国产精品福利观看| 国产精品视频一| 国产欧美一区二区三区四区| 欧美精品激情在线| 97精品久久久| 亚洲性无码av在线| 国产色婷婷国产综合在线理论片a| 91系列在线播放| 精品亚洲一区二区三区| 国产亚洲欧美日韩美女| 欧美久久精品一级黑人c片| 国产suv精品一区二区三区88区| 亚洲第一精品福利| 亚洲另类欧美自拍| 日韩精品中文字幕久久臀| 亚洲石原莉奈一区二区在线观看| 久久久久亚洲精品成人网小说| 中文字幕亚洲一区二区三区| 成人日韩av在线| 国产精品自拍偷拍| 欧美裸体xxxx极品少妇软件| 国产精品久久久久久久久久99| 国产一区二区三区三区在线观看| 亚洲自拍偷拍一区| 久久五月情影视| 中文字幕亚洲欧美日韩在线不卡| 丝袜美腿精品国产二区| 国产精品96久久久久久| 国产欧美精品xxxx另类| 亚洲精品国产精品乱码不99按摩| 亚洲欧洲日产国产网站| 91九色综合久久| 成人高清视频观看www| 黄网站色欧美视频| 日韩电影中文字幕在线| 色噜噜亚洲精品中文字幕| 欧美午夜丰满在线18影院| 亚洲欧美激情精品一区二区| 九九热在线精品视频| 欧美激情二区三区| 国产综合久久久久| 欧美激情精品久久久久久黑人| 精品日本美女福利在线观看| 亚洲图片在线综合| 国语对白做受69| 国产日韩欧美在线| 亚洲综合自拍一区| 少妇高潮久久久久久潘金莲| 国产亚洲精品久久久久久牛牛| 久久久久久国产精品美女| 久久久久久国产精品久久| 亚洲热线99精品视频| 超碰精品一区二区三区乱码| 日韩天堂在线视频| 国产精品视频网址|