日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

C# 4

發(fā)布時(shí)間:2023/12/20 C# 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C# 4 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 屬性
?? 1. 1.程序集屬性(AssemblyInfo.cs)
?? 2. 2.反射
?? 3. 3. 內(nèi)置屬性
?? 4. 4.定制屬性
2. XML文檔說(shuō)明
?? 1. 5.添加X(jué)ML文檔說(shuō)明
?? 2. 6. XML文檔說(shuō)明的注釋元素
?? 3. 7.生成XML文檔說(shuō)明文件
?? 4. 8.使用XML文檔說(shuō)明
3. 網(wǎng)絡(luò)
?? 1. 9.聯(lián)網(wǎng)概述
?? 2. 10.名稱的解析
?? 3. 11. 統(tǒng)一資源表示符
?? 4. 12.TCP 和UDP
?? 5. 13.應(yīng)用協(xié)議
?? 6. 14.網(wǎng)絡(luò)編程選項(xiàng)
?? 7. 15.WebClient
?? 8. 16. WebRequest 和 WebResponse
?? 9. 17.TcpListener 和 TcpClient
4. GDI+簡(jiǎn)介
?? 1. 18.圖形繪制概述
????? 1. Graphics類
????? 2. 對(duì)象的刪除
????? 3. 坐標(biāo)系統(tǒng)
????? 4. GraphicsPaths
????? 5. Regions
????? 6. 使用Pen類繪制線條
?? 2. 19.使用Brush類繪制圖形
?? 3. 20.使用Font類繪制文本
?? 4. 21.使用圖像進(jìn)行繪制
????? 1. 使用紋理畫筆繪圖
????? 2. 使用鋼筆繪制圖像
????? 3. 雙倍緩沖
?? 5. 22. GDI+高級(jí)功能介紹

________________
屬性
1.程序集屬性(AssemblyInfo.cs)
??? using System.Reflection;
??? using System.Runtime.CompilerServices;
??? using System.Runtime.InteropServices;
??? // 有關(guān)程序集的常規(guī)信息通過(guò)下列屬性集
??? // 控制。更改這些屬性值可修改
??? // 與程序集關(guān)聯(lián)的信息。
??? [assembly: AssemblyTitle("AresT")]????
??? [assembly: AssemblyDescription("")]????
??? [assembly: AssemblyConfiguration("")]???
??? [assembly: AssemblyCompany("ARES LAB")]????
??? [assembly: AssemblyProduct("AresT")]
??? [assembly: AssemblyCopyright("Copyright ARES LAB 2009")]
??? [assembly: AssemblyTrademark("")]
??? [assembly: AssemblyCulture("")]

??? [assembly:...]屬性定義;在程序集中存儲(chǔ)屬性的過(guò)程稱為"pickling".

??? Microsoft把一些最常見(jiàn)的屬性映射到Detail屬性表上,但其他屬性就必須用編寫代碼了,可以使用 Ildasm 或 Reflector工具。

??????? 添加Ildasm的方法,在VS2008 -? Tools -? External Tools -? 命令設(shè)置為C:/Program Files/Microsoft SDKs/Windows/V6.0/bin/ildasm.exe.


??? 在AssemblelyInfo.cs代碼中,使用了術(shù)語(yǔ)AssemblyTitle,但在IL中使用AssemblyTitleAttribute。C#編譯器會(huì)分別查找這兩個(gè)術(shù)語(yǔ)。

???

??? 屬性是一個(gè)包含程序集中其他數(shù)據(jù)的類,這些數(shù)據(jù)涉及到程序集或程序集中的任何類型。


??? AssemblyTitle屬性有一個(gè)構(gòu)造函數(shù),該構(gòu)造函數(shù)只有一個(gè)參數(shù)--字符串值。要訪問(wèn)這個(gè)值,可以用標(biāo)準(zhǔn)的Windows Explorer屬性表,或者用Ildasm or Reflector查看程序集。


2.反射
??? 反射可以用編程的方式檢查程序集,獲得該程序集的信息,包括其中包含的所有對(duì)象類型。這些信息還包含用戶添加到這些類型中的屬性。反射類位于System.Reflection名稱空間中。

??? 除了讀取給定程序集中定義的類型外,還可以使用System.Reflector.Emit 或 System.CodeDom的服務(wù)程序生成自己的程序集 和 類型。


??? 例:檢查一個(gè)程序集,并顯示定義的屬性,生成一個(gè)列表

??????? using System;

??????? using System.Reflector;

???????

??????? namespace FindAttributes

??????? {
??????????? class Program

??????????? {
??????????????? static void Main(string[] args)

??????????????? {
???????????????????? .......
???????????

???????????????????? try

???????????????????? {
???????????????????????? Assembly a = Assembly.LoadForm(assemblyName);

???????????????????????? object[] attributes = a.GetCustomerAttributes(true);

???????????????????????? if(attributes.Length ?0)

???????????????????????? {
???????????????????????????? console.WriteLine("Assembly attributes fo '{0}'...", assemblyName);

???????????????????????????? foreach(object o in attributes)

???????????????????????????? {
???????????????????????????????? Console.WriteLine("??? {0} ", o.ToString());

???????????????????????????? }
???????????????????????? }

???????????????????????? else

??????????????????????? ....................
???????????????????? }
??????????????? }

??????????? }

??????? }???


3. 內(nèi)置屬性
*???? System.Diagostics.ConditaionalAttribute
*???? System.ObsoleteAttribute
*???? System.SerializableAttribute
*???? System.Reflection.AssemblyDelaySignAttribute

??? System.Diagostics.ConditaionalAttribute
??? 這是最常用的屬性之一,它允許在編譯時(shí),根據(jù)符號(hào)的定義包含或不包含代碼塊。這個(gè)屬性包含在System.Diagnostics名稱空間中,該名稱空間包含調(diào)試 和 跟蹤輸出的類、事件日志、性能計(jì)數(shù)器 和 繼承信息。

??? 例:

??????? using System;
??????? using System.Diagnostics;

???

??????? namespace TestConditional

??????? {
??????????? class Program

??????????? {
??????????????? static void Main (string[] args)

??????????????? {
??????????????????? Program.DebugOnly();

??????????????? }


??????????????? [conditional("DEBUG")]??? //只有在編譯期間定義了DEBUG符號(hào),才會(huì)調(diào)用該方法;在VS2008中,編譯一個(gè)調(diào)試版程序,會(huì)自動(dòng)設(shè)置DEBUG符號(hào)。

??????????????? public static void DebugOnly()

??????????????? {
??????????????????? console.WriteLine("this string only displays in debug");

??????????????? }

??????????? }

??????? }


??? Debug塊的默認(rèn)設(shè)置是定義DEBUG 和 TRACE符號(hào)。

??? 在命令行上定義一個(gè)符號(hào)的方法:

??????? ?csc /d:DEBUG conditional.cs


??? conditional屬性只能用于無(wú)返回值的方法,否則刪除調(diào)用就以為著沒(méi)有返回值,但可吧方法設(shè)置為帶out 或 reg參數(shù),便令仍保留為原始值。


??? System.Diagnostics名稱空間中,Debug類有許多用[Conditional("DEBUG")]標(biāo)記的靜態(tài)方法,用于運(yùn)行應(yīng)用程序輸出調(diào)試信息。如果,改為成承發(fā)布版本,對(duì)這些方法的所有調(diào)用就會(huì)在最終的程序中被忽略。

??? 這非常適合于再添加調(diào)試信息,并在構(gòu)建項(xiàng)目的最終發(fā)布版本時(shí)自動(dòng)刪除它們。


??? System.ObsoleteAttribute

??? Obsolete屬性可以把類,方法 或 程序集中的其他項(xiàng)標(biāo)記為不再使用。

??? 用來(lái)提示,有新的功能可以使用,可以替代當(dāng)前功能。比如:"***以過(guò)時(shí),可以使用****方法"

???

??? public class Coder

??? {
??????? public Coder()

??????? {}


??????? [Obsolete("CodeInCSharp instead. ")]
??????? public void CodeInCPlusPlus()

??????? {}

??? }

??? 然后加入新方法:

??? public class CodeInCSharp()

??? {}


??? 當(dāng)使用CodeInCPlusPlus方法時(shí),會(huì)提示有新的方法CodeInCSharp可以使用。


??? System.SerializableAttribute

??? 序列化是指存儲(chǔ)和獲取磁盤文件、內(nèi)存或其他位置上的對(duì)象。


??? 在序列化時(shí),所有的實(shí)例數(shù)據(jù)都保存到存儲(chǔ)介質(zhì)上;
??? 在取消序列化時(shí),對(duì)象會(huì)重新構(gòu)建,且與其原實(shí)例完全相同。


??? ISerializable是一種改變序列化的數(shù)據(jù)的高級(jí)方式。

???

??? 例:

??? [Serializable]

??? public class Person

??? {
??????? public Person()
??????? {}


??????? public int Age(get ; set;);

??????? public int WeightInPounds{get;set;};

??? }


??? //下面用binaryFormatter存儲(chǔ)Person對(duì)象:

??? using System;

??? using System.Runtime.Serialization.Formatters.Binary;

??? using System.IO;

???

??? public static void Serialize()

??? {
??????? Person me = new Person();

??????? me.Age = 38;

??????? me.WeightInPounds =200;

??????? Stream s File.Open ("Me.dat", FileMode.Create);

??????? BinaryFormatter bf = new BinaryFormatter();

??????? bf.Serialize(s,me);

??????? s.Close();

??? }

???

??? [NonSerialized]屬性,定義一個(gè)或多個(gè)不要序列化的字段。

???

??? [Serializable]

??? public class Person

??? {
??????? public Person()

??????? {}

??????? public int Age {get;set;};

??????? [NonSerialized]

??????? private int _weightInPounds;

???????

??????? public int WeightInPounds

??????? {
??????????? get {return _weightInPounds;};

??????????? set {_weightInPounds = value;};

??????? }

??? }

??? 序列話這個(gè)類到時(shí)候,只儲(chǔ)存了Age成員,沒(méi)有存儲(chǔ)WeghtInPounds成員。

???

??? 解序:

??????? public static void DeSerialize()

??????? {
??????????? Stream s = File.Open("Me.dat", FileMode.Open);

??????????? BinaryFormatter bf = new BinaryFormatter();

??????????? object o = bf.Deserialize();

??????????? Person p = o as Person;

??????????? if(p!= null)

??????????????? Console.WriteLine(.........);

??????????? s.Close();

??????? }

???

??? System.Reflection.AssemblyDelaySignAttribute

??? AssemblyDelaySign,它允許用戶給程序集加上“延遲標(biāo)記”,即可以在GAC中注冊(cè)它,以便在沒(méi)有私鑰時(shí)測(cè)試它們。


??? 延遲標(biāo)記 的 一種是用場(chǎng)合時(shí) 開(kāi)發(fā)商用軟件。
??? 在室內(nèi)開(kāi)發(fā)的每個(gè)程序集在銷售給客戶之前,都需要用公司的私鑰標(biāo)記,向客戶保證,程序集的確是用公司創(chuàng)建的。
??? 所以,當(dāng)編譯程序的時(shí),應(yīng)在GAC中注冊(cè)它之前引用密鑰文件。密鑰文件保護(hù)兩個(gè)密鑰:公鑰 和 私鑰。

??? 但,許多組織并不想它們的私鑰出現(xiàn)在每個(gè)開(kāi)發(fā)人員的機(jī)器上。因此,運(yùn)行庫(kù)允許部分的標(biāo)記程序集,變換幾個(gè)設(shè)置,使程序集可以在GAC中注冊(cè)。

??? 在全部測(cè)試完畢后,就可以由擁有私鑰文件的人來(lái)標(biāo)記它。


??? 例:延遲標(biāo)記

??? 1)用程序 sn.exe創(chuàng)建一個(gè)密鑰。

??????? 這個(gè)密鑰包含:公鑰 和 私鑰。一般用公司命名它,擴(kuò)展名是.snk.

??????? ?sn -k Company.key

??? 2) 提取Public key。

??????? 接著,使用-p選項(xiàng)獲取開(kāi)發(fā)人員使用的公鑰部分:

??????? ?sn -p Company.key Company.public

??????? 這個(gè)命令會(huì)生成一個(gè)密鑰文件Company.public,其中只有包含密鑰的公共部分。

??????? 公鑰不需要保密,私鑰需要保密。company.key需要存儲(chǔ)在安全的地方,在最終標(biāo)記程序集時(shí)應(yīng)用。
??? 3)獲取公鑰記號(hào)。
??????? 為了給程序集加上延遲標(biāo)記,并在GAC中注冊(cè)它,還需要得到公鑰記號(hào)。
??????? 記號(hào)基本上是公鑰的一個(gè)縮寫版本,在注冊(cè)程序集時(shí)使用它??梢杂孟旅鎯煞N方式獲取該記號(hào):???

?????????? a.從公鑰本身獲取:
??????????? ?sn -t Company.Public
?????????? b.從使用該密鑰標(biāo)記的任何程序集中獲取:

??????????? ?sn -t ?assembly?
?????????? 這兩個(gè)命令都會(huì)顯示公鑰的散列版本,且是區(qū)分大小寫的。

??? 4)延遲標(biāo)記程序集

??????? using System;???

??????? using System.Reflection;

???????

??????? [assembly:AssemblyKeyFile("Company.Public")]? //定義了在哪里尋找密鑰??梢允枪€文件,也可以是保護(hù)公鑰和私鑰的文件。

??????? [assembly:AssemblyDelaySign(true)]??? //false時(shí),完整標(biāo)記了程序集;true時(shí),延遲標(biāo)記程序集

??????? public class DelayedSigning

??????? {
??????????? public DelayedSigning()

??????????? {}

??????? }


??????? 在編譯時(shí),程序集將在清單中包含用于公鑰的一項(xiàng)。還包括用于私鑰的足夠空間,所以重新標(biāo)記程序集肯定不會(huì)改變它(而是把額外的字節(jié)寫到程序集清單中)。

??????? 調(diào)試該程序集,會(huì)得到錯(cuò)誤提示。


??????? 這是因?yàn)樵谀J(rèn)情況下,.net運(yùn)行庫(kù)只加載未標(biāo)記的程序集(沒(méi)有定義密鑰文件)或 運(yùn)行完全標(biāo)記的、包含公鑰 和 私鑰對(duì)的程序集。

??????? .net不允許加載部分標(biāo)記的程序集。所以,會(huì)顯示錯(cuò)誤提示。
??? 5)在GAC中注冊(cè)

??????? 如果試圖使用Gacutil工具,在GAC中注冊(cè)一個(gè)延遲標(biāo)記的程序集,就會(huì)產(chǎn)生如下錯(cuò)誤:

??????????? microsoft (R) .net global assembly cache utility. version 3.5.20706.1

??????????? copy right (c) microsoft corporation. all rights reserved.

??????????? Failure adding assembly to the cache:strong name signature could not be verified.
??????????? Was the assembly built delay-signed?
??????? 此程序集只進(jìn)行了部分標(biāo)記,在默認(rèn)情況下,GAC和VS2008只接受有完整強(qiáng)名的程序集。
??????? 但對(duì)于延遲標(biāo)記的程序集,可以使用sn實(shí)用程序指示.NET跳過(guò)強(qiáng)名驗(yàn)證:
??????? ?sn -Vr? *,a1aad1......???? //a1aad1...... 是前面的公鑰記號(hào)

??????? 這將指示.NET允許在GAC中注冊(cè)公鑰記號(hào)為a1aad1......的程序集。
??????? 更重要的是,對(duì)于這個(gè)示例,它允許在VS中運(yùn)行DelaySign .exe.在命令提示行上輸入這個(gè)名利,會(huì)得到如下提示:

??????? microsoft (R) .NET Framework strong name utility version 3.5.20706.1

??????? copyright (C) microsoft corpration. all rights reserved

??????? Verification entry added for assembly '*, a1aad1......


??????? 現(xiàn)在就可以成功的用Gacutil將程序集安裝到GAC上了。
??????? 在為程序集添加驗(yàn)證項(xiàng)時(shí),指定注冊(cè)的所有程序集的命令:
??????? ?sn -Vr? *????????
??????? 也可以:

??????? 通過(guò)程序集的完整名稱來(lái)定義:

??????? ?sn -Vr DelaySign.exe

???

??????? 這些數(shù)據(jù)會(huì)永遠(yuǎn)保存在Verification Skip Table中。要得到該表,應(yīng)輸入下述命令:

??????? ?sn -Vl

???????

??????? 下面是輸出:

??????? microsoft..................

??????? copyright.................


??????? assembly/strong Name??????????????? users

??????? =============================

??????? *,a1ad1a5619382d41??????????????? All user

??????? 可以定義某個(gè)給定的程序集能由部分用戶加載到GAC中,參閱sn.exe文檔說(shuō)明。

??? 5)完整強(qiáng)名

??????? 這個(gè)過(guò)程的最后一項(xiàng)是把公鑰 和 私鑰 編譯到程序集中。

??????? 待有這兩項(xiàng)的程序集稱為完整的強(qiáng)名,可以在GAC中注冊(cè),且不必跳過(guò)驗(yàn)證項(xiàng)。

??????? 再次使用sn.exe使用程序,是用-R選項(xiàng),重新標(biāo)記程序集,并添加私鑰部分:

??????? ?sn -R delaysign.dll Company.Key

??????? comany.key為包含公鑰 和 私鑰的密鑰文件。


4.定制屬性
???

??? 定制屬性必須遵循以下兩個(gè)規(guī)范:

??? a.屬性必須派生于System.Attribute

??? b. 屬性的構(gòu)造函數(shù)之能包含可再編譯時(shí)解析的類型,例如,字符串和整數(shù)

??? 屬性構(gòu)造函數(shù)的參數(shù) 的類型限制 源于屬性存儲(chǔ)在程序集元數(shù)據(jù)中的方式。

??? [assembly:AssemblyKeyFile("CompanyPublic.snk")]

???

??? 1)自己定制 BugFixAttribute
??? 在編寫產(chǎn)品代碼時(shí),最好能自動(dòng)生成在應(yīng)用程序的各個(gè)版本之間已經(jīng)完成的修改操作。一般需要查看錯(cuò)誤數(shù)據(jù)庫(kù),檢查在兩個(gè)日期之間添加的錯(cuò)誤和改進(jìn),該從這些數(shù)據(jù)中生成報(bào)告。
???

??? 另一種方式,把修噶操作的細(xì)節(jié)嵌入代碼中,這樣可以根據(jù)代碼生成報(bào)告。

???

??? 創(chuàng)建一個(gè)定制屬性類:

* 創(chuàng)建一個(gè)派生于 System.Attribute的類;
* 按照需要?jiǎng)?chuàng)建構(gòu)造函數(shù) 和 公共屬性;
* 給類添加屬性,以定義可以在什么地方使用定制屬性。
??????? a.創(chuàng)建定制屬性類:

??????? 只需創(chuàng)建一個(gè)派生自System.Attribute的類即可。

??????? public class BugFixAttribute:Attribute

??????? {??? }
??????? b.創(chuàng)建構(gòu)造函數(shù) 和 屬性:
??????? 當(dāng)用戶使用屬性時(shí),都會(huì)調(diào)用該屬性的構(gòu)造函數(shù)(對(duì)于BugFixAttribute,要記錄錯(cuò)誤號(hào)和注釋)。???

??????? using System;

??????? public class BugFixAttribute:Attribute

??????? {
??????????? public BugFixAttribute(string bugNumber, string comments)?? //構(gòu)造函數(shù)

??????????? {
??????????????? BugNumber = bugNumber;

??????????????? Comments = comments;

??????????? }


??????????? public readonly string BugNumber;??????? //屬性

??????????? public readonly string Comments;???

??????? }

??????? c.標(biāo)記類的用途

??????? 最后需要標(biāo)記屬性類,指定在什么地方可以使用這個(gè)屬性類。

??????? 對(duì)于,BugFixAttribute,指定這個(gè)屬性只在類、屬性、方法和構(gòu)造函數(shù)上有效。

??????? [AttributeUsage(AttributeTargets.Class|AttributeTargets.Property|
?????????????????????????????? AttributeTargets.Method | AttributeTargets.Constructor, AllowMultiple=false, Inherited=true)]

??????? public class BugFixAttribute:Attribute

??????? .....

???????

??????? 定義好屬性BugFixAttribute后,就可以開(kāi)始用它編碼了。

??????? [BugFix("101","Created some methods")]

??????? pbulic class MyBuggyCode

??????? {
??????????? [BugFix("90125","Removed call to base")]

??????????? public MyBuggyCode()

??????????? {}

???????????

??????????? [BugFix("2112","Returned a non null string")]

??????????? [BugFix("38382","Returned OK")]

??????????? public string DoSomething()

??????????? {
??????????????? return "OK";?
??????????? }

??????? }

???????

??? 2)System.AttributeUsageAttribute

??? 在定義定制屬性類時(shí),需要添加AttributeUsage定義可以在什么地方使用。


??? 最簡(jiǎn)單的格式如下:

??? [AttributeUsage(AttributeTargets.Class|AttributeTargets.Property|
?????????????????????????????? AttributeTargets.Method | AttributeTargets.Constructor, AllowMultiple=false, Inherited=true)]


??? AttributeTargets枚舉定義了表 30-2中所示的成員:
??? All :屬性在程序集的任何地方都有效

??? Assembly:屬性在程序集上有效

??? Class:屬性在類定義上有效。TestCase屬性就使用這個(gè)值,另一個(gè)示例是Serializable屬性

??? Constructor:屬性近在類的構(gòu)造函數(shù)中有效

??? Delegate:屬性僅在委托中有效

??? Enum:屬性可以添加到枚舉值中。

??? Event:屬性在事件定義上有效

??? Field:屬性可以放在字段上

??? Interface:屬性在接口上有效。例:在System.Runtime.InteropServices中定義的GuidAttribute,它允許顯示地定義接口的GUID

??? Method:屬性方法上有效。System.Runtime.Remoting.Message中的OneWay屬性就是用這個(gè)值

??? Module:屬性在模塊中有效。程序集可以從許多代碼模塊中創(chuàng)建,所以可以使用這個(gè)值把屬性房子一個(gè)單獨(dú)的模塊上,而不是房子整個(gè)程序集上

??? Parameter:屬性可應(yīng)用于方法定義中的一個(gè)參數(shù)上

??? Property:屬性可以用于一個(gè)特性

??? Return Value:屬性與函數(shù)的返回值相關(guān)

??? Struct:屬性在結(jié)構(gòu)上有效


??? a.屬性的作用域

??? [assembly:AssemblyTitle("AssemblyPeek")]????? 字符串指定了屬性的作用域

???

???? [return:MyAttribute()]??? 屬性作用于返回值

???? public long DoSomething()

???? {
??????? ...

???? }

????

???? b.AttributeUsage.AllowMutiple

???? [AttributeUsage(AttributeTargets.Class|AttributeTargets.Property|
?????????????????????????? AttributeTargets.Method | AttributeTargets.Constructor
?????????????????????????? , AllowMultiple=false, Inherited=true)]
???? AttributeUsage 的構(gòu)造函數(shù)只帶一個(gè)參數(shù):可以使用屬性的標(biāo)志列表。AllowMultiple是AttributeUsage上的一個(gè)特性。
???? 使用一個(gè)類似的方法設(shè)置Inherited屬性(如果,定制屬性有特性,就可以用相同的方法設(shè)置它們)。


???? 添加錯(cuò)誤修改者的姓名:

???? public readonly string BugNumber;

???? public readonly string Comments;

???? public string Author = null;

???? public override string ToString()
???? {
??????? if(null== Author)

??????????? return string.Format("BugFix {0} : {1}", BugNumber, Comments);

??????? else

??????????? return string.Format("BugFix {0} by {1} : {2}", BugNumber,Author,Comments);

???? }

???? 報(bào)告類的錯(cuò)誤更正的方法時(shí)將類的類型(也在System.Type中)傳遞給下面所示的DisplayFixes函數(shù),
???? 這也使用反射來(lái)查找應(yīng)用到類上的錯(cuò)誤更正,再迭代這個(gè)類上的所有方法,查找BugFix屬性:

???

???? public static void DisplayFixes(System.Type T)

???? {
??????? object[] fixes = t.GetCustomerAttributes (typeof (BugFixAttribute), false);
??????? Console.WrtieLine("Displaying fixes for {0}",t);


??????? foreach(BugFixAttribute bugFix in fixes)

??????? {
??????????? Console.WriteLine("? {0}",bugFix);
??????? }

??????????????????????????????????????????????????????????????????????? //下面的參數(shù),限制了返回的成員列表;BindingFlags枚舉在System.Reflector中定義
???????? foreach(MemberInfo member in t.GetMembers (BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static))?
???????? {
??????????? object[] memberFixes = member.GetCustomerAttributes(typeof(BugFixAttribute),false);

??????????? if(memberFixes.Length?0)

??????????? {
??????????????? Console.WriteLine("? {0}", member.Name );

??????????????? foreach(BugFixAttribute memberFix in memberFixes)

??????????????????? Console.WriteLine("? {0}", memberFix);

??????????? }

???????? }?????
???? }


???? 對(duì)于前面給出的MyBuggyCode類,將得到如下結(jié)果:

???? Displaying fixes for MyBuggyCode

??????? BugFix 101 : Created some methods

??????? DoSomething

??????????? BugFix 2112 : Returned a non-null string

??????????? BugFix 38382 : Returned OK???

??????? .ctor

??????????? BugFix 90125: Removed call to base()

??? 如果要顯示給定程序集中所有類的錯(cuò)誤更正,可以使用反射類獲取程序集中的所有類型,把每個(gè)類型傳遞給靜態(tài)方法BugFixAttribute.DisplayFixes。
???

??? c.AttributeUsage.Inherited

??? 通過(guò)設(shè)置這個(gè)標(biāo)志可以把屬性定義為可繼承:

???? [AttributeUsage(AttributeTargets.Class ,Inherited=true)]
???? public class BugFixAttribute{...}

????

??? 這表示BugFix屬性可以由使用該屬性的任何子類繼承。即錯(cuò)誤更正會(huì)應(yīng)用到某個(gè)類上,并且還會(huì)應(yīng)用到一些派生類上。
??? ------------------

??? 了解了定制屬性知識(shí)后,就會(huì)考慮可以把額外的信息添加到程序集的什么地方。
??? 我們可以提取這里定義的BugFix屬性,并擴(kuò)展它——例如,要定義更正了錯(cuò)誤的軟件版本號(hào),可以使用反射查找BufFix屬性;
??? 再比較該更正的版本號(hào)與終端用戶要求查看的版本號(hào),向終端用戶顯示應(yīng)用程序的給定版本中所有已更正的錯(cuò)誤。

???

??? 這也是和與在產(chǎn)品循環(huán)的最后生成文檔說(shuō)明,列出最終版本中的所有錯(cuò)誤更正。
??? 顯然,必須依賴開(kāi)發(fā)人員添加這些熟悉,但可以建立代碼檢查循環(huán),確保所有的錯(cuò)誤更正都在代碼中做了說(shuō)明。

________________
?XML文檔說(shuō)明
??????? XML文檔說(shuō)明,它允許在源代碼中位所創(chuàng)建的類包含語(yǔ)法、幫助和示例。XML文檔說(shuō)明可以用做項(xiàng)目的MSDN連接的起點(diǎn),或者使用XSLT格式化XML文檔說(shuō)明,毫不費(fèi)力地獲得即時(shí)HTML文檔說(shuō)明。

??????? 把這個(gè)創(chuàng)建文檔說(shuō)明的功能內(nèi)置于用于開(kāi)發(fā)代碼的工具中是非常有用的。盡管給代碼添加X(jué)ML文檔說(shuō)明很費(fèi)時(shí)間,但對(duì)于最終結(jié)果是值得的。


5.添加X(jué)ML文檔說(shuō)明
??? 添加X(jué)ML文檔說(shuō)明時(shí),使用三個(gè)斜杠,而不是兩個(gè)進(jìn)行注釋。

??? ///(XML Documentation goes here.)

??? class MyClass

??? {
??????? ///(And here)???

??????? public void MyMethod()

??????? {
??????????? ......

??????? }

??? }


??? 注意:XML文檔說(shuō)明不能應(yīng)用于名稱空間聲明

??? XML文檔說(shuō)明一般占用多行,使用XML文檔說(shuō)明符號(hào)來(lái)標(biāo)記:

??? ///?XMLDocElement?

??? ///Content.

??? ///More Content

??? ///?/XMLDocElement?

??? class MyClass

??? {
??????? ......

??? }


??? XML文檔說(shuō)明中最基本的元素是?summary?,它提供了類型或成員的簡(jiǎn)短描述。

??? ///?summary?

??? /// this is a summary description for the DocumentedClass class

??? ///?/summary?

??? public class DocumentClass

??? {
??????? .....

??? }

??? 在IntelliSense中會(huì)顯示;

??? 打開(kāi)Object Browser窗口,展開(kāi)FirstXMLDocumentation屬性的項(xiàng),單擊DocumentedClass,在右下角的匯總信息中顯示。


6. XML文檔說(shuō)明的注釋元素
??? XML文檔說(shuō)明中基本元素的簡(jiǎn)短描述:

??? ?c?:格式化代碼字體中的文本。它用于潛在其他文本中的單個(gè)代碼字

??? ?code?:格式化代碼字體中的文本。它用于未嵌在其他文本中的多行代碼

??? ?description?:把文本標(biāo)記為項(xiàng)的描述,用做列表中?item?或?listheader?的子元素
??? ?example?:把文本標(biāo)記為目標(biāo)的示例用法

??? ?exception?:指定由目標(biāo)拋出的異常

??? ?include?:從外部文件中獲得XML文檔說(shuō)明

??? ?item?:表示列表中的一項(xiàng),用做?list?的子元素,可以有?description?和?term?子元素

??? ?list?:定義一個(gè)列表,可以有?listheader?和?term?子元素

??? ?listheader?:表示表格的標(biāo)題行,用作?list?的子元素,可以有?description?和?term?子元素

??? ?para?:用于把文本分解為各個(gè)段落

??? ?param?:描述模板的一個(gè)參數(shù)

??? ?paramref?:引用一個(gè)方法參數(shù)

??? ?permission?:指定目標(biāo)需要的許可

??? ?remarks?:與目標(biāo)的相關(guān)的其他信息

??? ?return?:描述目標(biāo)的返回值,與方法一起使用

??? ?see?:引用另一個(gè)目標(biāo),在元素體中使用,如?summary?

??? ?seealso?:應(yīng)用國(guó)另一個(gè)目標(biāo),通常在其他元素的外部或最后使用,如?summary?

??? ?summary?:與目標(biāo)相關(guān)的匯總信息

??? ?term?:把文本標(biāo)記為項(xiàng)的定義

??? ?typeparam?:描述用于一般目標(biāo)的類型參數(shù)

??? ?typeparamref?:引用一個(gè)類型參數(shù)

??? ?value?:描述模板的返回值,與屬性一起使用

???

??? 1)文本格式化元素:

??? ?c?,?code?,?list?及相關(guān)元素?para?,?paramref?。
??? ?see?、?seealso?比較特殊,也可以包含在這個(gè)表中,因?yàn)樗鼈兛梢园谖谋倔w中,但通常放在最后。


??? ?see?,?seealso?,?paramref?和?typeparamref?

??? 這四個(gè)元素都用于表示項(xiàng)目的XML文檔說(shuō)明中的 其他項(xiàng) 或 外部的MSDN項(xiàng)。
??? 它們都顯示為一個(gè)超鏈接,允許文檔說(shuō)明瀏覽器調(diào)到其他項(xiàng)上。

??? ?see?和?seealso?通過(guò)cref屬性指定其目標(biāo),目標(biāo)可以是任意類型 或 任意類的成員,在項(xiàng)目中或其他地方。

??? ?paramref?和?typeparamref?使用name屬性引用當(dāng)前目標(biāo)的一個(gè)參數(shù)。

??? ///?summary?

??? ///?para????

??? ///This method uses ?paramref name="museName" /? to choose a muse

??? /// for more details, see ?see cref="MyPoet" /?.

??? ///?/para?

??? ///?seealso cref="MyParchment" /?

??? ///?seealse cref="MyTheme" /?

??? ///?/summary?

???

??? ?see?在使用屬性langword引用C#關(guān)鍵字時(shí)特別有用。

??? ///?summary?

??? ///For more information, see? ?see langword="null" ?

??? ///?/summary?

??? 優(yōu)點(diǎn)是,如果指定語(yǔ)言專用的關(guān)鍵字,它就可以為其他語(yǔ)言修改文檔說(shuō)明。


??? 注意,這些元素不包括要顯示的文本,要顯示的文本通常從name、ref 或 langword 屬性中構(gòu)造。

??? 例:

??? /// this method uses ?paramref name="museName"? /? museName to choose a muse.

??? 其中,museName會(huì)重復(fù)。


??? ?list?和相關(guān)元素

???? ?list?元素是最復(fù)雜的文本格式化元素,因?yàn)榭梢砸圆煌姆椒ㄊ褂盟?
??? 它的type屬性可以是:

* bullet——格式化帶項(xiàng)目符號(hào)的列表
* number——格式化帶編號(hào)的列表
* table——格式化表格
???? ?list?元素一般包含一個(gè)?listheader?子元素 和 幾個(gè)?item?子元素。這些子元素都有許多?term?和?description?子元素。

???? 選擇哪種子元素取決于列表的類型 和 工具格式化列表的方式。例如:
???? ?term?在格式化的表格中使用,而?listheader?僅在表格中有意義。

??? 對(duì)于帶項(xiàng)目符號(hào)的列表,可以使用:?
??? ///?summary?

??? ///?para?

??? ///This method uses ?paramref name="museName" /? to choose a muse

??? ///?/para?

??? ///?para?

??? ///try the following muses:

??? ///?list type="bullet"?

??? ///?listheader?

??? ///?term? Muse name ?/term?

??? ///?description? Muse's favorite pizza ?/description?

??? ///?/listheader?

??? ///?item?

??? ///?term?Calliope?/term?

??? ///?description? Ham & Mushroom ?/description?

??? ///?/item?

??? ///?item?

??? ///?term?Clio?/term?

??? ///?description? Four Seasons?/description?
??? ///?/list?

??? ///?/para?

??? ///?/summary?


??? 2)主要的結(jié)構(gòu)元素

??? ?summary? 該元素從不會(huì)包含在其他元素中,且總是用于給出目標(biāo)的匯總信息。

??? ?example?、?exception?、?param?、?permission?、?remarks?、?returns? 和 ?value?。

??? ?seealso?比較特殊,它可以是頂級(jí)元素,也可以是另一個(gè)元素的子元素。

??? ?include?是另一個(gè)比較特殊的元素,它可以從外部文件中獲取XML,有效的重寫其他元素。


??? ?summary?、?example?和?remarks?

??? 這三個(gè)元素都提供目標(biāo)的一般信息。這些信息顯示在工具提示中,所以最好使該信息較短,而把其他信息放在?example?和?remarks?中

???

??? 介紹一個(gè)類時(shí),給出該類的用法示例 常常比較有效。這也適用于方法、屬性等。這些信息放在?example?中。

??? ///?summary?

??? ///?para?

??? ///this summary is about a ?c? class ?/c? that does interesting things.

??? ///?/para?

??? ///?example?

??? ///?para?

??? ///try this:

??? ///?/para?

??? ///?code?

??? /// MyPoet poet = new MyPoet("Homer");

??? ///poet.AddMuse("Thalia");

??? ///poet.WriteMeAnEpic();

??? ///?/code?

??? ///?/example?

??? 同樣,?remark?常常用于提供目標(biāo)的較長(zhǎng)描述,可以包含?see?和?seealso?元素,進(jìn)行交叉引用。

??? ?param?和?typeparam?

??? 這些元素描述一般目標(biāo)的參數(shù),可以是標(biāo)準(zhǔn)方法的參數(shù)或類型參數(shù)。

??? 要引用的參數(shù)用name屬性來(lái)設(shè)置。如果使用了多個(gè)參數(shù),元素可以出現(xiàn)多次:

??? ///?summary?

??? ///Method to add a muse

??? ///?/summary?

??? ///?param name="museName"?

??? ///A ?see langword="string" /? parameter specifying the nameof a muse.
??? ///?/param?
??? ///?param name="museModd"?
??? ///A ?see cref="MuseMood" /? parameter specifying the mood of a muse.?

??? ///?/param?


??? ?returns? 和 ?value?

??? 它們都表示返回值,其中?return?用于方法的返回值,?value?用于屬性值,這兩個(gè)元素都不適用任何屬性。

??? 對(duì)于方法:

??? ///?summary?
??? ///Method to add a muse

??? ........
??? ///?returns?
??? ///the return value of? this method is? ?see langword="void"?

??? ///?/returns?

??? 對(duì)于屬性:

??? ///?summay?

??? ///Property for getting / setting a muse

??? ///?/summary?

??? ///?value?

??? ///the type of this property is ?see langword="string" /?

??? ///?/value?


??? ?permission?

??? 這個(gè)元素用于描述與目標(biāo)相關(guān)的許可??蓪?shí)際上設(shè)置許可應(yīng)采用其他方式;
??? 例如,把屬性PermissionSetAttribute應(yīng)用于方法,?permission?元素僅允許通知其他人有這些許可。

??? ?permission?元素包含一個(gè)cref屬性,以便引用包含附加信息的類,如,System.Security.PermissionSet。
??? 例:
??? ///?permission cref="System.Security.PermissionSet"?
??? ///Only administrators can use this method
??? ///?/permission????


??? ?exception?
??? 這個(gè)元素用于描述使用目標(biāo)的過(guò)程中可能拋出的異常。它的cref屬性可用于交叉應(yīng)用異常類型。

??? 例如:
??? 試商用這個(gè)元素可以說(shuō)明屬性的取值范圍,還可以說(shuō)明如果試圖把屬性設(shè)置為不允許的值,會(huì)發(fā)生什么情況

??? ///?exception cref="System.ArgumentException"?

??? ///This exception will be thrown if you set ?paramref name="Width" /? to a

??? /// nagative value

??? ///?/exception?

???

??? ?seealso?

??? 該元素可以用作頂級(jí)元素??梢允褂脦讉€(gè)?seealso?元素,根據(jù)所使用的工具,該元素在目標(biāo)的最后格式化為一個(gè)引用列表:

??? ///?summary?

??? ///this is a summary for the MyPoet class

??? ///?/summary?

??? ///?seealso cref="MyParchment" /?

??? ///?seealso cref="MyTheme" /?

??? ///?seealso cref="MyToenails" /?


??? ☆?include?

??? 可以把說(shuō)明文檔放在完全獨(dú)立的文件中。

??? ?include?元素通過(guò)兩個(gè)屬性file和path允許這么做。

??? 例:

??? ///?include file="ExternalDoc.xml" path="documentation/classes/MyClass/*" /?

??? public class MyClass

???

??? 上面所引用的ExternalDoc.xml文件,包含如下代碼:

??? ??xml version="1.0" encoding="utf-8"?

??? ?documentation?

??????? ?classes?

??????????? ?MyClass?

??????????????? ?summary?

??????????????????? summary in an external file

??????????????? ?/summary?

??????????????? ?remarks?

??????????????????? Nice,eh?

??????????????? ?/remarks?

??????????? ?/MyClass?

??????? ?/classes?

??? ?/documentation?

??? 這些代碼等價(jià)于:

??? ///?summary?

??? ///Summary in an external file

??? ///?/summary?

??? ///?remarks?

??? ///Nice.eh?

??? ///?/remarks?

??? public class MyClass


7.生成XML文檔說(shuō)明文件
??? 如果要對(duì) 用與開(kāi)發(fā)項(xiàng)目環(huán)境的XML說(shuō)明文檔 進(jìn)行操作,就必須把項(xiàng)目的文檔說(shuō)明輸出為XML文件。

??? 為此,需要修改項(xiàng)目的構(gòu)建設(shè)置(winform項(xiàng)目上右擊,選擇屬性,選擇“build”or “生成”標(biāo)簽)

??? 唯一改變是選中了XML documentation file復(fù)選框,提供了一個(gè)輸出文件名,最好在程序集所在的目錄下保存XML文檔說(shuō)明文件,

??? 因?yàn)镮DE會(huì)在該目錄下搜索XML文檔說(shuō)明。

??? 比如:bin/debug/DiagramaticDocumentation.xml

????????

??? 如果,客戶應(yīng)用程序在另一個(gè)解決方案中解釋程序集,則只有IDE找到XML文檔說(shuō)明文件,才能利用IntelliSense 和 Object Browser的幫助。
??? 打開(kāi)XML文檔說(shuō)明的設(shè)置后,編譯器就配置為主動(dòng)搜索類中的XML文檔說(shuō)明。忽略給定類 或 方法的XML文檔說(shuō)明不一定會(huì)出錯(cuò),但I(xiàn)DE會(huì)在Error List窗口中發(fā)出警告。

??? 生成的文檔包含以下內(nèi)容:

*???? 跟級(jí)?doc?元素,它包含其他所有信息
*???? ?assembly?元素,它包含一個(gè)?name?元素,而?name?元素包含應(yīng)用XML文檔說(shuō)明的程序集名
*???? ?members?元素,它包含程序集中每個(gè)成員的XML文檔說(shuō)明
*???? 幾個(gè)?member?元素,每個(gè)元素都帶有一個(gè)name屬性,說(shuō)明?member?元素包含的XML文檔說(shuō)明應(yīng)用于什么類型 或 成員
*???? ?member?元素的name屬性遵循同一個(gè)命名模式。它們都屬于下述名稱空間之一,即,它們都是以下面的一個(gè)字母開(kāi)頭:
*???? T:指定成員是一個(gè)類型(類、接口、結(jié)構(gòu)、枚舉或委托)
*???? M:指定成員是一個(gè)方法
*???? P:指定成員是一個(gè)屬性 或 索引符
*???? F:指定類型是一個(gè)字段或枚舉成員
*???? E:指定成員是一個(gè)事件
???

??? 在類型XML文檔說(shuō)明中,錯(cuò)誤會(huì)在生產(chǎn)的文件中顯示為一個(gè)加了注釋的?member?元素:

??? ?!-- Badly formed XML comment ignored for member "T:DiagramticDocumentation.DocumentedClass" --?


8.使用XML文檔說(shuō)明
??? 1)編程處理XML文檔說(shuō)明
??? XML文檔說(shuō)明最明顯的用法是充分利用.NET名稱空間中豐富的XML工具。

??? 可以XML文檔說(shuō)明加載到XmlDocument對(duì)象中。

??? 例:

??? using System;

??? ....

??? using System.xml;

??? static void Main(string[] args)

??? {
??????? //load XML documentation file

??????? XmlDocument doucumentation = new XmlDocument();

??????? documentation.Load(@"../../../DocumentedClassses"+@"/DocumentedClasses/bin/debug/DocumentedClasses.xml");

???????

??????? //Get ?member? elements.

??????? XmlNodeList memberNodes = documentation.SelectNodes("//member"); //使用XPath表達(dá)式//member,獲得?member?所有元素列表

???????

??????? //Extract ?member? elements.

??????? List?XmlNode? typedNodes = new List?XmlNode?();

??????? foreach(XmlNode node in memberNodes)

??????? {
??????????? if(node.Attributes["name"].Value.StartsWith("T"))

??????????? {
??????????????? typeNodes.Add(node);

??????????? }

??????? }


??????? //Write types to the console

??????? Console.WriteLine("Types:");

??????? foreach (XmlNode node in typedNodes)

??????????? Console.WriteLine("-{0}", node.Attributes["name"].Value.Substring(2));


??????? Console.ReadKey();
??? }

???

??? 2)用XSLT格式化XML文檔說(shuō)明

??? 可以使用XSLT把XML轉(zhuǎn)換成HTML,甚至是用XSLT格式化對(duì)象,創(chuàng)建可以打印的文檔說(shuō)明。

??? 這里采用C#創(chuàng)始人Anders Heejlsberg的建議。他發(fā)布一個(gè)XSLT文檔和相關(guān)CSS樣式表,可以把XML文檔說(shuō)明轉(zhuǎn)換為HTML。


??? 說(shuō)明文件中添加一個(gè)預(yù)處理指令,如下:

??? ??xml version="1.0" ??
??? ??xml:stylesheet href="doc.xsl" type="text/xsl" ?????? //doc.xsl 和 doc.css

??? ?doc?

??? ......

??? ?/doc?

??????

??? 3)文檔說(shuō)明工具

??? 另一種方式是使用工具。

??? XML文檔說(shuō)明樣式化的首選工具是NDoc,這個(gè)第三方工具可以把文檔說(shuō)明轉(zhuǎn)換為多種樣式,包括MSDN樣式的幫助文件。

??? http://ndoc.sourceforge.net/ 可以得到免費(fèi)最新版本。

??? NDoc可能會(huì)被轉(zhuǎn)讓,所有應(yīng)該看看另一個(gè)工具Sandcastle,Microsoft使用這個(gè)工具生成API文檔說(shuō)明,所有其功能也很全面。

??? 但是,Sandcastle是一個(gè)內(nèi)部工具,使用起來(lái)不太容易。

??? 這個(gè)工具包含幾個(gè)GUI,大多是用戶創(chuàng)建的。

??? ☆web站點(diǎn):

??? http://blogs.msdn.com/sandcastle上包含更多信息

??? http://www.codeplex.com/shfb 可以下載Sandcastl的流行GUI

??? http://www.microsoft.com/Downloads/details.aspx?FamilyID=e82ea71d-da89-42ee-a715-696e3a4873b2&displaylang=en 程序下載
???

________________
網(wǎng)絡(luò)
9.聯(lián)網(wǎng)概述
??? 聯(lián)網(wǎng)就是與其他系統(tǒng)上的應(yīng)用程序通信。通信是通過(guò)發(fā)送消息來(lái)實(shí)現(xiàn)的。消息可以發(fā)給單個(gè)系統(tǒng),但在發(fā)送消息之前,要先建立連接。

??? 消息也可以通過(guò)廣播(broadcast)發(fā)送給多個(gè)系統(tǒng),使用廣播時(shí),不需要建立連接,而是把消息發(fā)送給網(wǎng)絡(luò)。

??? OSI 7層模型

??? 應(yīng)用層,顯示層,會(huì)話層,傳輸層,網(wǎng)絡(luò)層,數(shù)據(jù)鏈路層,物理層

???

??? 數(shù)據(jù)鏈路層要進(jìn)行錯(cuò)誤更正,流控制和硬件尋址。

???

??? 網(wǎng)絡(luò)層使用邏輯地址查找WAN中的系統(tǒng)。

??? Internet Protocol(IP)是第3層上的協(xié)議,在第3層上,使用IP地址尋址其他系統(tǒng)。 IPV4上,地址包含4個(gè)字節(jié)。


??? 傳輸層用于表示通信的應(yīng)用程序。應(yīng)用搞程序可以用端點(diǎn)來(lái)標(biāo)識(shí)。等待客戶機(jī)連接的服務(wù)器應(yīng)用程序有一個(gè)已知的端點(diǎn)用于連接。

??? 傳輸控制協(xié)議(TCP)和用戶數(shù)據(jù)報(bào)協(xié)議(UDP)都是第4層上的協(xié)議,使用端口號(hào)(端點(diǎn))來(lái)標(biāo)識(shí)應(yīng)用程序。

??? TCP協(xié)議用于可靠通信,連接時(shí)在數(shù)據(jù)發(fā)送之前建立的。


??? 會(huì)話層定義了應(yīng)用程序的服務(wù),會(huì)話層支持應(yīng)用程序之間的虛擬連接。

???

??? 顯示層考慮的是數(shù)據(jù)的格式,在這個(gè)層中,可以對(duì)數(shù)據(jù)進(jìn)行加密,解密和壓縮。

???

??? 應(yīng)用層為應(yīng)用程序提供聯(lián)網(wǎng)功能,例如,文件傳輸、電子郵件、web瀏覽等。


??? 在TCP/IP協(xié)議組中,應(yīng)用級(jí)協(xié)議覆蓋了OSI層模型的第4~7層。該協(xié)議組中有HTTP(超文本傳輸協(xié)議),FTP(文件傳輸協(xié)議)和 SMTP(簡(jiǎn)單郵件傳輸協(xié)議)。

??? 在傳輸層,端點(diǎn)用于到達(dá)其他應(yīng)用程序,這些應(yīng)用協(xié)議定義了發(fā)送到其他系統(tǒng)的數(shù)據(jù)的外觀。

???

10.名稱的解析
??? IPv6中,IP地址有128位組成,而不是32位(IPv4)。

??? 為了把主機(jī)名映射為IP地址,需要使用Domain Name System(DNS)服務(wù)器。

????
??? ☆Windows有一個(gè)命令行工具 nslookup,可以查找名稱(從主機(jī)名種解析出IP地址,或者從IP地址中解析出主機(jī)名)。

???

??? 通過(guò)System.Net名稱空間中的DNS類來(lái)解析名稱。利用DNS類可以把主機(jī)名解析為IP地址,或把IP地址解析為主機(jī)名。

??? 例:

??? using System.Net;

??? .....


??? static void Main(string[] args)

??? {
??????? if(args.Length !=1)

??????? {
??????????? Console.WriteLine("Usage:DnsLookup hostname/IP Address");

??????????? return;

??????? }


??????? IPHostEntry ipHostEntry = Dns.GetHostEntry(args[0]);???


??????? Console.WriteLine("Host:{0} ", ipHostEntry.HostName);


??????? if(ipHostEntry.Aliases.Length?0)

??????? {
??????????? Console.WriteLine("/nAliases:");

??????????? foreach(string alias in ipHostEntry.Aliases)

??????????? {
??????????????? Console.WrtieLine(alias);

??????????? }

??????? }


??????? Console.WriteLine("/nAddress(es):");

??????? foreach(IPAddress address in ipHostEntry.AddressList)

??????????? Console.WriteLine("Address:{0}", address.ToString());

??? }

??? GetHostEntry()方法,給它傳主機(jī)名,該方法就會(huì)返回一個(gè)IPHostEntry。

??? GetHostByAddress()方法,給它傳一個(gè)IP地址,該方法返回一個(gè)IPHostEntry。

???

??? Dns類總是返回一個(gè)IPHostEntry。這個(gè)類包含主機(jī)的信息。
??? IPHostEntry包含3個(gè)屬性:
??????? HostName返回主機(jī)名,
??????? Aliases返回所有別名的列表,
??????? AddressList返回IPAddress元素?cái)?shù)組。?????????????????????????????????????????????????????????????????????????????

??? IPAddress類的ToString()方法以標(biāo)準(zhǔn)記號(hào)法返回Internet地址。


11. 統(tǒng)一資源表示符
??? URI(Uniform Resource Identifier,統(tǒng)一資源標(biāo)識(shí)符)

??? 類Uri封裝了URI,它的屬性和方法用于解析、比較和合并URI。

??? 把一個(gè)URI字符串傳遞給構(gòu)造函數(shù),就可以創(chuàng)建一個(gè)Uri對(duì)象:

??? Uri uri = new Uri("http://www.areslab.com/dotnet");;

???

??? 如果一個(gè)站點(diǎn)上 有許多不同的頁(yè)面,就可以使用一個(gè)基本URI,根據(jù)它構(gòu)造包含目錄的URI:

??? Uri baseUri = new Uri("http://msdn.microsoft.com");

??? Uri uri = new Uri(baseUri, "downloads");

???

??? 使用Uri類的屬性可以訪問(wèn)URI的各個(gè)部分。

??? 例:

??? 設(shè) URI 為 http://www.areslab.com/marketbasket.cgi?isbn=0470124725

????
Uri屬性 ?結(jié)果 ?
Scheme ?http ?
Host ?www.areslab.com ?
Port ?80 ?
LocalPath ?/marketbasket.cgi ?
Query ??isbn=0470124725 ?

12.TCP 和UDP
??? 這兩個(gè)協(xié)議都是用端口號(hào)標(biāo)識(shí)要接收數(shù)據(jù)的應(yīng)用程序。???

??? TCP協(xié)議時(shí)面向連接的,而UDP協(xié)議時(shí)無(wú)連接的

??? TCP協(xié)議需要服務(wù)器應(yīng)用程序用一只的端口號(hào)創(chuàng)建一個(gè)套接字,這樣客戶應(yīng)用程序才能連接服務(wù)器。

??? 客戶程序用任意端口號(hào)創(chuàng)建一個(gè)套接字。

??? 1)在客戶機(jī)連接服務(wù)器時(shí),客戶機(jī)會(huì)把他的端口號(hào)發(fā)送給服務(wù)器,這樣服務(wù)器才能知道到達(dá)客戶機(jī)的路徑;

??? 2)在建立好連接后,客戶機(jī)就可以發(fā)送由服務(wù)器接收的數(shù)據(jù),接著服務(wù)器再發(fā)送一些客戶機(jī)接收的數(shù)據(jù)。


??? 發(fā)送和接收也可以使用其他方式,通過(guò)QOTD(qutoe of the day)協(xié)議(QOTD服務(wù)器是Windows組件Simple TCP/IP Service的一部分)

??? 服務(wù)器將只在客戶機(jī)打開(kāi)連接后才發(fā)送數(shù)據(jù),然后關(guān)閉連接。


??? 在UDP協(xié)議中,服務(wù)器也必須使用已知的端口號(hào)創(chuàng)建一個(gè)套接字,客戶機(jī)也要使用任意的端口號(hào)。

??? UDP和TCP的區(qū)別是,客戶機(jī)不必啟動(dòng)連接,而可以在未建立連接的情況下發(fā)送數(shù)據(jù)。

??? 沒(méi)有連接,就不能保證服務(wù)器能接收到數(shù)據(jù),但整體效果是傳輸比較快。
??? UDP協(xié)議有一大優(yōu)點(diǎn):可以進(jìn)行廣播——使用一個(gè)廣播地址把信息發(fā)送給LAN中的所有系統(tǒng)。

??? 廣播地址是一個(gè)IP地址,但I(xiàn)P地址中主機(jī)部分的所有位置都設(shè)置為1.

???

13.應(yīng)用協(xié)議
??? 使用TCP 和 UDP的應(yīng)用協(xié)議。

??? HTTP就是一個(gè)以TCP為基礎(chǔ)的應(yīng)用協(xié)議。

??? 使用HTTP協(xié)議請(qǐng)求Web服務(wù)器上的數(shù)據(jù)時(shí),要打開(kāi)一個(gè)TCP連接,再發(fā)送HTTP請(qǐng)求。

??? 例:

??? 瀏覽器發(fā)出的HTTP請(qǐng)求如下所示:

??? GET /default.aspx HTTP/1.1?? //GET命令, 定義HTTP版本

??? Accept:image/gig, image/x-xbitmap,image/jpeg,image/pjpeg,??? //以下是Http標(biāo)題信息
??????? application/x-ms-application,application/vnd.ms-xpsdocument,??? //支持的程序類型

??????? application/xaml+xml,application/x-xbap,application/x-shockwave-flash,???

??? */*???

??? Accept-Language:da-AT,en-us;q=0.7??? //Brower使用的語(yǔ)言

??? Accept-Encoding:gzip,deflate

??? User-Agent:Mozilla/4.0 (compatible; MSIE 7.0;Windwos NT 6.0;.NET CLR
???????? 2.0.50727;Media Center PC 5.0; Tablet PC 2.0; .NET CLR 1.1.14322; .NET CLR
???????? 3.5.520706; .NET CLR 3.0.590)

??? Host:localhost:80

??? Connection:Keep-Alive?? //在Http1.1中可使用同一個(gè)連接


??? 最常用的HTTP命令有GET,POST 和 HEAD。

??? GET用于從服務(wù)器上請(qǐng)求文件,POST命令也用于從服務(wù)器上請(qǐng)求文件,但與GET命令不同的是,POST命令還在HTTP標(biāo)題之后發(fā)送給其他數(shù)據(jù)。
??? 使用HEAD命令,服務(wù)器只返回文件的標(biāo)題信息,讓客戶機(jī)確定該文件是否不同于高速緩存中已有的數(shù)據(jù)。

???

??? 服務(wù)器接收到GET請(qǐng)求后,就返回一個(gè)響應(yīng)消息:

??? HTTP/1.1 200 OK

??? Server:Microsoft-IIS/7.0

??? Date:Sun,29 Jul 2007 20:14:59 GMT

??? X-Powered-By:ASP.NET

??? X-AspNet-Version:2.0.50727

??? Cache-Control:private

??? Content-Type:text/html; charset=utf-8

??? Content-Length:991


??? ?!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"?

??? ?HTML?

??????? ?HEAD?

??????????? ?title?Demo?/title?

??? .............
14.網(wǎng)絡(luò)編程選項(xiàng)
??? System.Net 和 System.Net.Sockets名稱空間提供了一個(gè)網(wǎng)絡(luò)編程的幾個(gè)選項(xiàng)。
??? 進(jìn)行網(wǎng)絡(luò)編程最簡(jiǎn)單的方式是使用WebClient類。

??? 使用這個(gè)類的方法,可以從Web服務(wù)器上獲取文件,或者把文件傳輸給FTP服務(wù)器。

??? 在.NET3.5中,只能通過(guò)HTTP和FTP協(xié)議使用它訪問(wèn)文件。
??? 當(dāng)然,也可以插入定制類,來(lái)支持其他協(xié)議。

???

??? Webclient類利用了WebRequest 和 WebResponse類。

???

??? 要?jiǎng)?chuàng)建服務(wù)器,就不能用WebClient 或 WebRequest,必須使用System.Net.Socket名稱空間中的TcpListener類。

??? TcpListener類可以用于為TCP協(xié)議創(chuàng)建一個(gè)服務(wù)器,而TcpClient類用于編寫客戶應(yīng)用程序。

??? 有了這些類,就不會(huì)被限制在HTTP和TCP協(xié)議上,而可以使用任意基于TCP的協(xié)議。


??? 如果要使用UDP協(xié)議,就應(yīng)使用UdpListener和UdpClient類(它們類似于TcpListener和TcpClient類)來(lái)編寫UDP服務(wù)程序和客戶程序。

??? 如果要獨(dú)立于協(xié)議,或需要TCP和UDP協(xié)議進(jìn)行更多的控制,就可以用.NET進(jìn)行套接字編程。用于套接字編程的類位于System.Net.Socket名稱空間中。

???
15.WebClient?
??? WebClient類的主要屬性和方法。

??? WebClient類的方法用于上載 和 下載文件。

???

??? WebClient屬性:

??? BaseAddress:屬性BaseAddress定義了WebClient發(fā)出的請(qǐng)求的基地址

??? Credentials:使用Credentials屬性可以傳送身份驗(yàn)證信息,例:使用NetWorkCredential類來(lái)傳送

??? UseDefaultCredentials:如果應(yīng)使用當(dāng)前登錄的用戶憑證,就把UseDefaultCredentials屬性設(shè)置true

??? Encoding:Encoding屬性用于把字符串的編碼設(shè)置為上載 和 下載

??? Headers:Headers屬性用于定義WebHeaderCollection,其中包含所用協(xié)議的特定標(biāo)題信息

??? Proxy:默認(rèn)使用通過(guò)Internet Exploer配置的代理程序訪問(wèn)Internet。如果需要其他代理程序,就可以用Proxy屬性定義一個(gè)WebProxy對(duì)象

??? QueryString:如果需要將查詢字符串發(fā)送給Web服務(wù)器,就可以用QueryString屬性設(shè)置NameValueCollection

??? ResponseHeaders:發(fā)送請(qǐng)求之后,就可以在與ResponseHeaders類關(guān)聯(lián)的WebHeaderCollection類中閱讀響應(yīng)的標(biāo)題信息


??? WebClient方法:

??? DownloadData():通過(guò)DownloadData()方法,可以給Web地址傳送一個(gè)放在BaseAddress后面的字符串和一個(gè)包含從服務(wù)器返回的數(shù)據(jù)字節(jié)數(shù)組

??? DownloadString():DownloadString()類似于DownloadData(),唯一的區(qū)別是返回的數(shù)據(jù)存儲(chǔ)在字符串

??? DownloadFile():如果服務(wù)器返回?cái)?shù)據(jù)應(yīng)存儲(chǔ)在文件夾中,就應(yīng)使用DownloadFile()方法。這個(gè)方法的參數(shù)是Web地址和文件名

??? OpenRead():使用OpenRead()方法,除了下載文件之外,還可以從服務(wù)器上下載數(shù)據(jù),下載的數(shù)據(jù)可以從這個(gè)方法返回的流中讀取

??? UploadFile():要給FTP或Web服務(wù)器上傳文件,可以使用UploadFile()方法。這個(gè)方法也允許傳送用于上傳的HTTP方法

??? UploadData():UploadFile()允許從本地文件系統(tǒng)中上傳文件,而UploadDatat()把字節(jié)數(shù)組發(fā)送給服務(wù)器

??? UploadString():使用UploadString()可以把字符串上傳給服務(wù)器

??? UploadValues():使用UploadValues()可以把Name ValueCollection上傳給服務(wù)器

??? OpenWrite():該方法使用流把內(nèi)容發(fā)送給服務(wù)器。


??? 例:

??? 使用WebClient類

??? static void Main()

??? {
?? ①? WebClient client = new WebClient();

?? ②? client.BaseAddress = "http://www.areslab.com";

?? ③? string data = client.DownloadString("Office");

??????? Console.WriteLine(data);???

??????? Console.ReadLine();

??? }

????
16. WebRequest 和 WebResponse
??? 除了WebClient類之外,還可以使用WebRequest類與Web或FTP服務(wù)器通信,讀取文件。

??? WebClient類在后臺(tái)也使用WebRequest。

???

??? WebRequest類總是和WebResponse類都是抽象類,因此不能直接使用。
??? 這些類都是基類,名稱空間System.Net為HTTP,FTP和文件協(xié)議提供了具體的實(shí)現(xiàn)方式。
??? 這些基類的具體實(shí)現(xiàn)方式是:
??? HttpWebRequest、HttpWebResponse、FtpWebResponse、FtpWebRequest、FileWebRequest和FileWebResponse。

??? HTTP協(xié)議由HttpWebXXX類使用,
??? FtpWebXXX類使用FTP協(xié)議,
??? FileWebXXX類允許用戶訪問(wèn)文件系統(tǒng)。

???

???
??? 例:

??? 從FTP服務(wù)器上下載文件

??? 首先,創(chuàng)建一個(gè)新的WPF應(yīng)用程序FtpClient;

??? 然后,在后臺(tái)代碼中,導(dǎo)入System.Net, System.IO 和 Microsoft.Win32

??? ① 建立與服務(wù)器的初始化連接

??????? private void buttonOpen_Click(object sender, RouterEventArgs e)

??????? {
??????????? Cursor currentCursor = this.Cursor;

??????????? FtpWebResponse response = null;

??????????? Stream stream = null;

??????????? try

??????????? {
??????????????? this.Cursor = Cursors.Wait;

??????????????? //Create the FtpWebRequest object

??????????? ① FtpWebRequest request = (FtpWebRequest)WebRequest.Create(textServer.Text);
??????????????? request.Credentials = new NetWorkCredential(textUsername.Text, passwordBox.password);
??????????????? request.Method = WebRequestMethods.Ftp.ListDirectory;

???????????

??????????????? //send the request and fill the list box

???????????? ② response = (FtpWebResponse)request.GetResponse();

???????????????

??????????????? //Read the response and fill the list box

???????????? ③ stream = response.GetResponseStream();???

???????????????? FillDirectoryList(stream); //填充listbox的方法
??????????????? ....???????????
??????????? }

??????????? catch(..)

??????????? ....

??????? }


?????? ②打開(kāi)服務(wù)器上的特定目錄

????????? private void buttonOpenDirectory_Click(object sender, RouteEventArgs e)

????????? {
??????????????? Cursor currentCursor = this.Cursor;

??????????????? FtpWebResponse response = null;
??????????????? Steam stream = null;

??????????????? try

??????????????? {
??????????????????? this.Cursor = Cursor.Wait;??? //鼠標(biāo)形狀

??????????????????? string subDirectory = ...........;
???

??????????????? ① Uri baseUri = new Uri(textServer.Text);

??????????????????? Uri uri = new Uri(baseUri, serverDirectory);

???????????????????

??????????????? ② FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);

??????????????????? request.Credentials = new NetworkCredential(textUsername.Text, passwordBox.password);

??????????????????? request.Method = WebRequestMethods.Ftp.ListDirectory;

??????????????????? response = (FtpWebResponse)request.GetResponse();


??????????????? ③ stream = response.GetResponseStream();

??????????????????? FillDirectoryList(stream);

??????????????? }

??????????????? catch(Exceptiron ex)

??????????????? {
??????????????????? MessageBox......;

??????????????? }

??????????????? finally

??????????????? {
??????????????????? if(response != null)

??????????????????????? response.Close();

??????????????????? if(stream != null)

??????????????????????? stream.Close();

??????????????????? this.Cursor = currentCursor; //鼠標(biāo)形狀

??????????????? }

????????? }

????????
??????? ③ 從服務(wù)器上下載文件

??????? private void ButtonGetFile_click(object sender , RoutedEventArgs e)

??????? {
??????????? Cursor currentCursor = this.Cursor;

??????????? FtpWebResponse response = null;
??????????? Steam inStream = null;
??????????? Steam outStream = null;

??????????? try

??????????? {
??????????????????? this.Cursor = Cursor.Wait;??
????????????????????????
??????????????? ① Uri baseUri = new Uri(textServer.Text);

??????????????????? string filename = list......;

??????????????????? string fullFilname = .......;

??????????????????? Uri uri = new Uri(baseUri, fullFilename);

???????????????????

??????????????? ② FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);

??????????????????? request.Credentials = new NetworkCredential(textUsername.Text, txtPasswordBox.Text);

??????????????????? request.Method = WebRequestMethods.Ftp.DownloadFile;

??????????????????? request.UseBinary = checkBoxBinary.Checked??false;

??????????????????? response = (FtpWebResponse)request.GetResponse();


??????????????? ③ inStream = response.GetResponseStream();

??????????????????? SaveFileDialog saveFileDialog = new SaveFileDialog();

??????????????????? saveFileDialog.FileName = filename;

???????????????????

??????????????????? if(saveFileDialog1.ShowDialog()==true)

??????????????????? {
??????????????? ④???? outStream = File.OpenWrite(saveFileDialog.FileName);

??????????????????????? byte[] buffer = new byte[8192];

??????????????????????? int size = 0;

??????????????????????? while ((size = inStream.Read(buffer, 0, 8192))?0 )??? //從FTP上返回的流在While中讀取,并寫入本地文件流

??????????????????????? {
??????????????????????????? outStream.Write(buffer,0,size);

??????????????????????? }

??????????????????? }

???????????????????
??????????? }

??????????? catch.....

??????????? ......

??????? }

??? 示例說(shuō)明:

??? 在給FTP服務(wù)器發(fā)送請(qǐng)求時(shí),
??? ①必須創(chuàng)建一個(gè)FtpWebRequest對(duì)象。
??????? FtpWebRequest對(duì)象由構(gòu)造方法WebRequest.Create()創(chuàng)建,

??????? 這個(gè)方法根據(jù)傳送給它的URL字符串,創(chuàng)建FtpWebRequest、HttpWebRequest 或 FileWebRequest對(duì)象。
??????? FtpWebRequest request = (FtpWebReuqest)WebRequest.Create(textSever.Text);

??? ②通過(guò)設(shè)置其他屬性來(lái)配置它。

??????? Credentials屬性允許設(shè)置用于訪問(wèn)服務(wù)器的用戶名和密碼。

??? ③Method屬性定義了要發(fā)送給服務(wù)器的FTP請(qǐng)求。


??? FTP協(xié)議,FTP協(xié)議允許使用的命令非常類似于HTTP協(xié)議命令。HTTP協(xié)議使用GET、HEAD和POST命令。

??? FTP協(xié)議命令在RFC959(www.ierf.org/rfc/rfc0959.txt)中定義,RETR用于文件下載,STOR用于上傳文件,MKD用于創(chuàng)建目錄,LIST用于從目錄中獲取文件。

??? 在.NET中,不需要了解所有命令,因?yàn)閃ebRequestMethods類定義了這些命令。

??????? WebRequestMethods.Ftp.ListDirectory創(chuàng)建一個(gè)要發(fā)送給服務(wù)器的LIST請(qǐng)求,

??????? WebRequestMethods.Ftp.DownloadFiles用于從服務(wù)器上下載文件。

??????? 例:

??????? request.Credentials = new NetWorkCredential(textUsername.Text,passwordBox.password);
??????? request.Method = WebRequestMethods.Ftp.ListDirectory;

???

??? 在定義請(qǐng)求時(shí),可以把請(qǐng)求發(fā)給服務(wù)器。GetResponse()方法會(huì)把請(qǐng)求發(fā)給服務(wù)器,并等待直到接受響應(yīng)。

??????? response = (FtpWebResponse)request.GetResponse();


??? 為了訪問(wèn)響應(yīng)中的數(shù)據(jù),GetResponseStream()方法返回一個(gè)流。

??????? 為了響應(yīng)WebRequestMethods.Ftp.ListDirectory請(qǐng)求,該響應(yīng)流包含了所請(qǐng)求服務(wù)器目錄中的所有文件名。
??????? 在WebRequestMethods.Ftp.DownloadFile請(qǐng)求之后,響應(yīng)會(huì)包含所請(qǐng)求文件的內(nèi)容。

??????? stream = response.GetResponseStream();

________________
17.TcpListener 和 TcpClient
??? System.Net.Sockets名稱空間中的類為網(wǎng)絡(luò)編程提供了更多控制。

??? TcpListener類可以在服務(wù)器上使用。
??? 可以用該類的構(gòu)造函數(shù)定義服務(wù)器監(jiān)聽(tīng)的端口號(hào),Start()方法會(huì)啟動(dòng)監(jiān)聽(tīng)。
??? 但,為了與客戶機(jī)通信,服務(wù)器必須調(diào)用AcceptTcpClient()方法,這個(gè)方法在建立與客戶機(jī)的連接之前是禁用的。

??? 其返回值是一個(gè)TcpClient對(duì)象,其中包含與客戶機(jī)的連接信息。

??? 使用這個(gè)TcpClient對(duì)象,服務(wù)器可以接收客戶機(jī)發(fā)送的數(shù)據(jù),并把數(shù)據(jù)發(fā)送回客戶機(jī)。


??? 客戶機(jī)也使用TcpClient類。

??? 客戶機(jī)可以用Connect()方法啟動(dòng)與服務(wù)器的連接,之后使用與TcpClient對(duì)象相關(guān)的流發(fā)送給接收數(shù)據(jù)。


??? 例:

??? 服務(wù)器給客戶機(jī)發(fā)送一組圖片文件,客戶機(jī)從其中選擇一個(gè)文件,向服務(wù)器請(qǐng)求這個(gè)文件。

??? 在這個(gè)應(yīng)用程序中,客戶機(jī)可以發(fā)出兩個(gè)請(qǐng)求:LIST請(qǐng)求返回文件列表,PICTURE:filename請(qǐng)求以字節(jié)流的形式返回圖片。

????
??? 創(chuàng)建TCP服務(wù)器:

??? ①創(chuàng)建一個(gè)控制臺(tái)程序。

??? ②創(chuàng)建默認(rèn)設(shè)置文件。
??????? 選擇項(xiàng)目屬性。打開(kāi)Setting選項(xiàng)卡。單擊This Project Does Not Contain A Default Setting File. Click Here To Create One.連接,創(chuàng)建一個(gè)默認(rèn)設(shè)置文件。

??? ③在Settings.settings文件中,添加一個(gè)字符串類型的PictureDirectory屬性,和一個(gè)int類型的Port屬性。

??????? PictureDirectory的value設(shè)置為一個(gè)目錄,比如:C:/PICTURES

??????? Port設(shè)置為8888,定義服務(wù)器的端口號(hào)。????
??? ④添加一個(gè)幫助類PictureHelper。

??????? 添加幾個(gè)靜態(tài)方法:

??????? GetFileList()返回所有文件的列表;

??????? GetFileListBytes()方法在字節(jié)數(shù)組中返回文件列表;

??????? GetPictureBytes()方法返回圖片文件的字節(jié)數(shù)組

??????? 這個(gè)類使用文件I/O獲取文件名并讀取文件。

??????? 例:

??????? using System;

??????? .....

??????? using System.IO;

??????? using System.Text;

???????

??????? namespace PictureServer

??????? {
??????????? internal static class PictureHelper???

??????????? {
??????????????? internal static IEnumerable?string? GetFileList()

??????????????? {
??????????????????? //Remove the directory path from the filename
??????????????????? return form file in Directory.GetFiles(Properties.Settings.Default.PictureDirectory)????
????????????????????????? select Path.GetFileName(file);
??????????????? }????????????????
??????????? }


??????????? internal static byte[] GetFileListBytes()

??????????? {
??????????????? try

??????????????? {
??????????????????? //LIST request - return list

??????????????????? IEnumerable?string? files = PictureHelper.GetFileList();

??????????????????? StringBuilder responseMessage = new StringBuilder();

??????????????????? foreach(string s in files)

??????????????????? {
??????????????????????? responseMessage.Append(s);
??????????????????????? responseMessage.Append(":");????
??????????????????? }

??????????????????? return Encoding.ASCII.GetBytes(responseMessage.ToString());

??????????????? }

??????????????? catch(DirectoryNotFoundException ex)

??????????????? {
??????????????????? Console.WriteLine(ex.Message);

??????????????????? throw;

??????????????? }

??????????? }

??????? }


??? ⑤在Program.cs文件中導(dǎo)入System.Net、System.Net.Sockets和System.IO名稱空間

??? ⑥在服務(wù)器應(yīng)用程序的Main()方法中添加如下代碼:

??????? class Program

??????? {
??????????? static void Mian()

??????????? {
??????????????? // 要?jiǎng)?chuàng)建一個(gè)服務(wù)器應(yīng)用程序,以使用TCP協(xié)議等待客戶機(jī)的連接,可以使用TcpListener類。


??????????????? //要?jiǎng)?chuàng)建TcpListener對(duì)象,必須為服務(wù)器指定端口號(hào),
??????????????? //這里使用Properties.Settings.Default.Port從配置文件中讀取端口號(hào),
?????????? ①? TcpListener listener = new TcpListener(IPAddress.Any,? Properties.Settings.Default.Port);

??????????????? //再調(diào)用Start()方法監(jiān)聽(tīng)傳入的請(qǐng)求。

?????????? ②? listener.Start();

??????????????? Console.WriteLine("Server running...");

???????????????

??????????????? while(true)

??????????????? {
??????????????????? const int bufferSize = 8912;
??????????????????? //啟動(dòng)監(jiān)聽(tīng)器后,服務(wù)器就在AcceptTcpClient()方法中等待客戶機(jī)與它連接。
??????????????????? //與客戶機(jī)的連接在AcceptTcpClient()方法返回的TcpClient對(duì)象中定義。????????????????????
???????????? ③??? TcpClient client = listener.AcceptTcpClient();??????????????
??????????????????? //啟動(dòng)連接后,客戶機(jī)就給服務(wù)器發(fā)送一個(gè)請(qǐng)求。
??????????????????? //該請(qǐng)求在流中讀取,client.GetStream()返回一個(gè)NetworkStream對(duì)象,這個(gè)網(wǎng)絡(luò)流中的數(shù)據(jù)被讀入到字節(jié)數(shù)組緩存中,

??????????????????? //再轉(zhuǎn)換為一個(gè)字符串,存儲(chǔ)在變量request中
???????????? ④??? NetworkStream clientStream = client.GetStream();

??????????????????? byte[] buffer = new byte[bufferSize];
??????????????????? int readBytes = 0;????
???????????? ⑤??? readBytes = clientStream.Read(buffer,0,bufferSize);
??????????????????? string request = Encoding.ASCII.GetString(buffer).Substring(0,readBytes);
???????????????????? //根據(jù)請(qǐng)求字符串,把一個(gè)圖片文件列表或圖片字節(jié)返回給客戶機(jī)。請(qǐng)求字符串使用String.StartWith進(jìn)行檢查

??????????????????? if(request.StartsWith("LIST",StringComparison.Ordinal))??
??????????????????? {
??????????????????????? //LIST request - return list

??????????????????????? //服務(wù)器把返回的數(shù)據(jù)寫入網(wǎng)絡(luò)流,將數(shù)據(jù)發(fā)送回客戶機(jī):

??????????????????????? byte[] responseBuffer = PictureHelper.GetFileListBytes();

??????????????????????? clientStream.Write(responseBuffer,0,responseBuffer.Length);??? //發(fā)送

??????????????????? }
??????????????????? else if(request.StartsWith("FILE",StringComparison.Ordinal))
??????????????????? {
??????????????????????? //FILE request - return file
??????????????????????? //get the filename
??????????????????????? string[] requestMessage = request.Split(':');
??????????????????????? string filename = requestMessge[1];
??????????????????????? byte[] data = File.ReadAllByte(Path.Combine(Properties.Settings.Default.PictureDirectory,filename));

???????????????????????

??????????????????????? //Send the picture to the client.

??????????????????????? clientStream.Write(data,0,data.Length);??? //發(fā)送

??????????????????? }
??????????????????? clientStream.Close();??
??????????????? }

??????????? }
??????? }
???????

??? 創(chuàng)建TCP客戶程序:
??? 客戶應(yīng)用程序時(shí)一個(gè)Windows窗體應(yīng)用程序,顯示服務(wù)器上可用的圖片文件,用戶選擇一個(gè)圖片后,該圖片就會(huì)顯示在客戶應(yīng)用程序中。

??? ①創(chuàng)建一個(gè)WPF項(xiàng)目。

??? ②創(chuàng)建一個(gè)WPF窗口PictureClientWindow.xaml。

??? ③將服務(wù)器名稱和端口添加到程序?qū)傩栽O(shè)置中
??????? 服務(wù)器名的屬性名是Server
??????? 服務(wù)器端口號(hào)屬性名是SeverPort。

??? ④設(shè)計(jì)UI

??? ⑤在PictureClientWindow.xaml.cs文件中導(dǎo)入System.Net, System.Net.Sockets和System.IO名稱空間

??? ⑥在PictureClientWindow類中添加bufferSizge常量:

??????? public partial class PictureClientWindow:window

??????? {
??????????? pivate const int bufferSizge = 8192;

??????????? .......

??????? }

??? ⑦添加幫助方法ConnectToServer()及其執(zhí)行代碼:
??????? TcpClient類通過(guò)客戶機(jī)連接服務(wù)器。

???????

??????? private TcpClient ConnectToServer()
??????? {
??????????? // Connect to the Server
???????? ① TcpClient client = new TcpClient();
???????? ② IPHostEntry host = Dns.GetHostEntry(Properties.Settings.Default.Server);
???????? ③ var addresss = (from h in host.AddressList
????????????????????????????????? where h.AddressFamily == AddressFamily.InterNetWork
????????????????????????????????? select h). First();??? //pick the first IP
???????? ④ client.Connect(address.ToString(),Properties.Settings.Default.ServerPort);??? //獲取端口號(hào)
??????????? return client;????
??????? }???????

???????

??? ⑧給buttonListPictures按鈕添加一個(gè)Click事件處理程序

??????? private void buttonListPictureList(object sender, RouteEventArgs e)

??????? {
??????????? TcpClient client = ConnectToServer();

??????????? //Send a request to the server

??????????? //NetworkStream可以把數(shù)據(jù)發(fā)送給服務(wù)器。

??????????? NetworkStream clientStream = client.GetStream();

??????????? string request = "LIST";

??????????? byte[] requestBuffer = Encoding.ASCII.GetBytes(request); //Encoding類把字符串LIST轉(zhuǎn)換為字節(jié)數(shù)組。

??????????? clientStream.Write(requestBuffer,0,requestBuffer.Length);?

???????????

??????????? //Read the response from the server

??????????? byte[] responseBuffer = new byte[bufferSize];
??????????? MemoryStream memStream = new MemoryStream();

??????????? int bytesRead = 0;

??????????? do
??????????? {
??????????????? bytesRead = clientStream.Read(resposneBuffer,0,bufferSize);? //從服務(wù)器返回的數(shù)據(jù)用clientStream對(duì)象的Read()方法讀取。

??????????????? memStream.Write(responseBuffer,0,bytesRead);?? //接收,寫入內(nèi)存

??????????? }? while(bytesRead?0);
??????????? clientStream.Close();
??????????? client.Close();

????????????
??????????? byte[] buffer = memStream.GetBuffer();
??????????? string response = Encoding.ASCII.GetString(buffer);
??????????? this.DataContext = response.Split(':');?
??????? }

??? ⑨ 給buttonGetPicture按鈕添加一個(gè)Click事件處理程序:

??????? private void buttonGetPicture_Click(object sender, RouteEventArgs e)

??????? {
??????????? TcpClient client = ConnectTtoServer();

??????????? NetworkStream clientStream = client.GetStream();

??????????? string request = "FILE:"+this.listFiles.SelectedItem.ToString();

??????????? byte[] requestBuffer = Encoding.ASCII.GetBytes(request);

??????????? clientStream.Write(requestBuffer,0,requestBuffer.Length);


??????????? byte[] responseBuffer = new byte[bufferSize];

??????????? MemoryStream memStream = new MemoryStream();

??????????? int bytesRead=0;

??????????? do

??????????? {
??????????????? bytesRead = clientStream.Read(responseBuffer,0,bufferSize);

??????????????? //寫入內(nèi)存

??????????????? memStream.Write(responseBuffer,0,byteRead);???????????????
??????????? }? while(bytesRead?0);

??????????? clientStream.Close();

??????????? client.Close();

???????????

??????????? //圖片的讀取方式與文件數(shù)據(jù)相同。內(nèi)存流使用WPF的BitmapImage類轉(zhuǎn)換為Image。

??????????? BitmapImage bitmapImage = new BitmapImage();

??????????? //從內(nèi)存中讀取圖片

??????????? memStream.Seek(0,SeekOrign.Begin);

??????????? bitmapImage.BeginInit();

??????????? bitmapImage.StreamSource = memStream;

??????????? bitmapImage.EndInit();


??????????? pictureBox.Source = bitmapImage;? //把圖像賦予PictureBox的Image屬性,使之顯示在窗體上。

??????? }

________________
GDI+簡(jiǎn)介
18.圖形繪制概述
??? 當(dāng)創(chuàng)建一個(gè)窗口,并在該窗口進(jìn)行繪圖時(shí),一般要聲明一個(gè)派生于System.Windows.Forms.Form的類。

??? 如果要編寫一個(gè)定制控件,就要聲明一個(gè)派生于System.Windows.Forms.UserControl的類。????
??? 在這兩種情況下,都重寫了虛擬函數(shù)OnPaint()。只要窗口的任何一部分需要重繪,Windows都會(huì)調(diào)用這個(gè)函數(shù)。


??? 在這個(gè)事件中,PaintEventArgs類作為參數(shù)被傳遞。

??? PaintEventArgs中有兩個(gè)重要信息:Graphics對(duì)象 和 ClipRectangle對(duì)象。
???
??? Graphics類
??? Graphics類封裝了一個(gè)GDI+繪圖接口。
??? 有3種基本類型的繪圖接口:

*???? 屏幕上的窗口和控件
*???? 要發(fā)送給打印機(jī)的頁(yè)面
*???? 內(nèi)存中的位圖和圖像
????
??? Graphics類提供了在這些繪圖界面上繪圖的功能。
??? 在其他功能中,我們可以使用它繪制圓弧、曲線、Bezier曲線、橢圓、圖像、線條、矩形和文本。

??? 給窗口獲得Graphics對(duì)象有兩種不同的方式:
??? ① 首先是重寫OnPaint()事件,Form類從Control類中集成了OnPaint()方法。

??????? 這個(gè)方法是Paint事件的處理程序,在重新繪制控件時(shí),就觸發(fā)這個(gè)事件。

??????? 從利用該事件傳入的PaintEventArgs中獲取Graphics對(duì)象:

??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Graphics g = e.Graphics;

??????????? //do our drawing here

??????? }

???????

??? ② 有時(shí),需要直接在窗口中繪圖,而無(wú)需等OnPaint()事件。比如,拖動(dòng)一些對(duì)象。

??????? 在窗體上調(diào)用CreateGraphics()方法就可以獲得一個(gè)Graphics對(duì)象,

??????? 這是Form類繼承自Control類的另一個(gè)方法:

??????? protected void Form1_Click(object sender, System.EventArgs e)

??????? {
??????????? Graphics g = this.CreateGraphics();

??????????? //Do our drawing here

??????????? g.Dispose();? //this is important

??????? }????
????????
??? 對(duì)象的刪除
??? 有幾種數(shù)據(jù)類型對(duì)于調(diào)用Dispose()是非常重要的,否則一些資源就不能釋放。
??? 這些類執(zhí)行IDisposable接口。Graphics是這些類中的一個(gè)。

???

??? 如果是從OnPaint()事件中獲得的Graphics對(duì)象,而不是創(chuàng)建了該對(duì)象,就不應(yīng)該調(diào)用Dispose(),
??? 但如果調(diào)用了CreateGraphics(),就必須調(diào)用Dispose()。


??? 對(duì)于實(shí)現(xiàn)IDisposeable的許多類來(lái)說(shuō),Dispose()方法會(huì)在析構(gòu)函數(shù)中自動(dòng)調(diào)用。

??? 但是,垃圾回收器(GC)不確定何時(shí)會(huì)運(yùn)行。內(nèi)存用盡后會(huì)觸發(fā)GC,但資源用盡后不會(huì)觸發(fā)GC。

??? Windows 2000和XP 對(duì)資源用盡的情況不是特別敏感。

??????? 根據(jù)規(guī)范,這兩個(gè)操作系統(tǒng)對(duì)這些類型的資源沒(méi)有任何限制,但當(dāng)打開(kāi)了太多的應(yīng)用程序時(shí),Windows 2000就會(huì)出錯(cuò)。


??? 另一種簡(jiǎn)單的方式是,使用Using結(jié)構(gòu)。

??? 在對(duì)象超出作用域時(shí),Using結(jié)構(gòu)會(huì)自動(dòng)調(diào)用Dispose()。

??? Using (Graphics g = this.CreateGraphics())

??? {
??????? g.DrawLine(Pens.Black, new Point(0,0), new Point(3,5));
??? }


??? 上面的代碼等于:

??? Graphics g = this.CreateGraphics();

??? try

??? {
??????? g.DrawLine(Pens.Black, new Point(0,0) , new Point(3,5));

??? }

??? finally

??? {
??????? if(g != null)

??????????? ((IDisposeable)g).Dispose();

??? }

??? 坐標(biāo)系統(tǒng)
??? 在繪圖時(shí),常常用3中結(jié)構(gòu)指定坐標(biāo):Point、Size和Rectangle

??? ①Point

??? GDI+函數(shù),例如DrawLine(),都把Point作為其參數(shù)。
??? 聲明和構(gòu)造Point的代碼如下:

??? Point p = new Point(1,1);
???

??? ②Size

??? Size結(jié)構(gòu)包含寬度和高度。

??? 聲明和構(gòu)造Size的代碼如下:

??? Size s = new Size(5,5);
??? Height 和 Width可以獲得 和 設(shè)置 Size的寬度 和 高度。


??? ③Rectangle

??? Rectangle有兩個(gè)構(gòu)造函數(shù)。

??? 一個(gè)構(gòu)造函數(shù)的參數(shù)是X坐標(biāo)、Y坐標(biāo)、寬度和高度;

??? 另一個(gè)構(gòu)造函數(shù)的參數(shù)是Point和Size結(jié)構(gòu)。

??? 聲明和構(gòu)造Rectangle的兩個(gè)示例如下所示:

??? 例1:
??? Rectangle r1 = new Rectangle(1,2,5,6);


??? 例2:

??? Point p = new Point(1,2);

??? Size s = new Size(5,6);

??? Rectangle r2 = new Rectangle(p,s);


??? GraphicsPaths
??? GraphicsPaths類表示一系列連接的線條和曲線。

??? 在構(gòu)造一條路徑時(shí),可以添加線條、Bezier曲線、圓弧、餅形圖、多邊形和矩形等。

??? 在構(gòu)造一條復(fù)雜的路徑后,可以用一個(gè)操作繪制路徑:

??????? 調(diào)用DrawPath();

??????? 可以用FillPath()填充路徑。

???

??? 可以使用一個(gè)點(diǎn)數(shù)組 和 PathTypes構(gòu)造GraphicsPath,
??? PathTypes是一個(gè)字節(jié)數(shù)組,其中的每個(gè)元素對(duì)應(yīng)于點(diǎn)數(shù)組中的每一個(gè)元素,

??? 并給出了路徑如何通過(guò)這些點(diǎn)來(lái)構(gòu)造的其他信息。通過(guò)點(diǎn)的信息可以使用PathPointType枚舉來(lái)獲得。

??????? 如果點(diǎn)式路徑的起始點(diǎn),那么這個(gè)點(diǎn)的路徑類型就是PathPointType.Start;

??????? 如果點(diǎn)是兩個(gè)線條的連接點(diǎn),那么這個(gè)店的路徑類型就是PathPointType.Line;

??????? 如果點(diǎn)用于購(gòu)置一條從前一點(diǎn)到厚一點(diǎn)之間的Bezier曲線,路徑類型就是PathPointType.Bezier。

???

??? 例:

??? 創(chuàng)建圖形路徑

??? using System;

??? .......

??? using System.Drawing.Drawing2D;

??? protected override void OnPaint(PaintEventArgs e)

??? {????
??????? GraphicsPath path;

??????? path = new GraphicsPath(new Point[]{ new Point(10,10),
???????????????????????????????????????????????????????????? new Point(150,10),

???????????????????????????????????????????????????????????? new Point(200,150),

???????????????????????????????????????????????????????????? new Point(10,150),

???????????????????????????????????????????????????????????? new Point(200,160)},

????????????????????????????????????????? new byte[] { new PathPointType.Start,
??????????????????????????????????????????????????????????? new PathPointType.Line,
??????????????????????????????????????????????????????????? new PathPointType.Line,
??????????????????????????????????????????????????????????? new PathPointType.Line,
??????????????????????????????????????????????????????????? new PathPointType.Line,});
??????? e.Graphics.DrawPath(Pens.Black, path);

??? }


??? Regions
??? Region類是一個(gè)復(fù)雜的圖形,由矩形和路徑組成。

??? 在構(gòu)造了一個(gè)Region后,就可以使用FillRegion()方法繪制該區(qū)域。

??? 創(chuàng)建區(qū)域:

??? ①創(chuàng)建Windows應(yīng)用程序

??? ②添加using System.Drawing.Drawing2D;

??? ③在Form1的主體中添加如下代碼:

??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Rectangle r1 = new Rectangle(10,10,50,50);

??????????? Rectangle r2 = new Rectangle(40,40,50,50);

??????????? Region r = new Region(r1);

??????????? r.Union(r2);


??????????? GraphicsPath path = new GraphicsPath(new Point[] {
??????????????????????????????????????????????????????????????????????????????????? new Point(45,45),

??????????????????????????????????????????????????????????????????????????????????? new Point(145,55),

??????????????????????????????????????????????????????????????????????????????????? new Point(200,150),

??????????????????????????????????????????????????????????????????????????????????? new Point(75,150),

??????????????????????????????????????????????????????????????????????????????????? new Point(45,45)},
???????????????????????????????????????????????????????????????? new byte[] {
??????????????????????????????????????????????????????????????????????????????????? (byte)PathPointType.Start,

??????????????????????????????????????????????????????????????????????????????????? (byte)PathPointType.Bezier,

??????????????????????????????????????????????????????????????????????????????????? (byte)PathPointType.Bezier,

??????????????????????????????????????????????????????????????????????????????????? (byte)PathPointType.Bezier,

??????????????????????????????????????????????????????????????????????????????????? (byte)PathPointType.Line

???????????????????????????????????????????????????????????????????????????????? });
??????????? r.Union(path);??? //如果決定使矩形和路徑相交,就可以用Inersection()方法替代Union方法。

??????????? e.Graphics.FillRegion(Brushes.Blue,r);

??????? }


??? 使用Pen類繪制線條
??? 該類定義了代碼繪圖時(shí)的顏色、線寬和線條的樣式。樣式表示該線條是實(shí)線,還是短線和點(diǎn)組成。

??? Pen類位于System.Drawing名稱空間中。

??? 例:

??? ①創(chuàng)建Windows應(yīng)用程序

??? ②在From的主體中添加代碼:

??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Graphics g = e.Graphics;? //因?yàn)閭魉土薌raphics對(duì)象的引用,而沒(méi)有創(chuàng)建它,所以不需要Dispose()


??????????? //因?yàn)槭褂昧苏加觅Y源非常大的Pen對(duì)象,所以要把其余代碼封裝到using塊中

??????????? //Pen對(duì)象應(yīng)總是調(diào)用Dispose()

??????????? using(Pen blackPen = new Pen(Color.Black,1))???

??????????? {
??????????????? //每個(gè)窗口都有一個(gè)客戶區(qū)域,定義了可以繪圖的區(qū)域。

??????????????? //可以利用ClientRectangle獲取客戶區(qū)域,這是一個(gè)只讀公共屬性(繼承于Control)

??????????????? if(ClientRectangle.Height/10?0)

??????????????? for(int y=0;y?ClientRectangle.Height;y+=ClientRectangle.Height/10)

??????????????? {
??????????????????? //在Pens類中獲得該P(yáng)en

??????????????????? g.DrawLine(blackPen,new Point(0,0), new Point(ClientRectangle.Wdith,y));

??????????????? }

??????????? }

??????? }

??? Pen的功能:

??????? 可以創(chuàng)建一個(gè)繪制虛線的鋼筆;也可以創(chuàng)建線寬比1個(gè)像素寬的鋼筆。

??????? Pen類有一個(gè)屬性Alignment,該屬性可以定義鋼筆是否從左向右(或從上到下)繪制指定的線條。

??????? 設(shè)置StartCap和EndCap屬性可以指定線條的末端箭頭、菱形、方框或圓形。

??????? CustomStartCap和CustomEndCap屬性編寫定制的起始端和終止端形狀。

??????? 何使用Pen指定Brush,通過(guò)位圖來(lái)繪制圖像,而不是一種單色。
________________
?19.使用Brush類繪制圖形
??? Brush是一個(gè)抽象類,要實(shí)例化一個(gè)Brush對(duì)象,應(yīng)使用派生于Brush的類,例如SolidBrush、TextureBrush和LinearGradientBrush。

??? Brush和SolidBrush類在System.Drawing名稱空間,但TextureBrush和LinearGradientBrush類在System.Drawing.Drawing2D名稱空間中。

*???? SolidBrush用一種單色填充圖形
*???? TextureBrush用一個(gè)位圖填充圖形
?? * 在構(gòu)造這個(gè)畫筆時(shí),還指定了邊框矩形和填充模式
?? * 邊框矩形指定畫筆使用位圖的哪一個(gè)部分——可以不用整個(gè)位圖
*???? LinearGradientBrush封裝了一個(gè)畫筆,可以繪制兩種顏色漸變的圖形
?? * 其中第一種顏色以指定的角度逐漸過(guò)渡到第二種顏色
?? * 角度的單位是度。0°表示顏色從左向右過(guò)渡。90°表示顏色從上到下過(guò)渡

??? 對(duì)于Brush對(duì)象總是要使用Dispose()


??? 例:

??? ①創(chuàng)建一個(gè)windows程序

??? ②添加System.Drawing.Drawing2D名稱空間

??? ③在Form類的構(gòu)造函數(shù)中,在InitializeComponent()調(diào)用的后面添加對(duì)SetStyle()的調(diào)用。

??????? public Form1()

??????? {????
??????????? InitializeComponent();

??????????? //SetStyle()它是Form類的一個(gè)方法。

??????????? //下面的代碼修改了Form類的作用,使之不能自動(dòng)繪制窗口的背景。
??????????? SetStyle(ControlStyles.Opaque, true);

??????? }

??? ④給類添加一個(gè)OnPaint()方法

??????? 與Pens類一樣,Brushes類包含的屬性可以創(chuàng)建大約150種畫筆。


??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Graphics g = e.Graphics;

??????????? //調(diào)用FillRectangle填充客戶區(qū)域的背景

??????????? g.FillRectangle(Brushes.White, ClientRectangle);

??????????? g.FillRectangle(Brushes.Red, new Rectangle(10,10,50,50));


??????????? //創(chuàng)建LinearGradientBrush要使用一個(gè)矩形指定矩形的大小,用兩種顏色進(jìn)行漸變,再制定角度

??????????? Brush linearGradientBrush = new LinearGradientBrush(new Rectangle(10,60,50,50), Color.Blue, Color.White, 45);

??????????? g.FillRectangle(linearGradientBrush, new Rectangle(10,60,50,50));

???????????

??????????? //Manually call Dispose()

??????????? linearGradientBrush.Dispose();

???????????

??????????? g.FillEllipse(Brushes.Aquamarine, new Rectangle(60,20,50,30));

??????????? g.FillPie(Brushes.Chartreuse, new Rectangle(60,60,50,50),90,210);

??????????? g.FillPolygon(Brushes.BlueViolet, new Point[])

??????? }


________________
?20.使用Font類繪制文本
??? Font類封裝了字體的3個(gè)主要特性:字體系列、字體大小和字體樣式。Font類在System.Drawing名稱空間中。

??? 字體的Size屬性表示字體類型的大小。

??? 它可以是點(diǎn)的大小,通過(guò)Unit屬性可以改變GraphicsUint屬性,Unit定義了字體的測(cè)量單位。
????

??? 使用Graphics對(duì)象的MeasureString()方法可以計(jì)算出給定字體的字符串寬度。

??? 字體的Style屬性表示該類型是否為斜體、黑體、刪除線 或 下劃線。

???

??? 對(duì)于Font對(duì)象總是要調(diào)用Dispose().


??? 在繪制文本時(shí),使用一個(gè)Rectangle指定要繪制文本的邊框坐標(biāo)。

??? 一般情況下,這個(gè)矩形的高度應(yīng)是字體的高度或字體高度的倍數(shù)。只有在使用剪切文本繪制某些特殊效果的文本時(shí),高度才有可能是其他值。

??? StringFormat類封裝了文本布局信息,包括對(duì)齊和行間距信息。

???

??? 例:

??? ①創(chuàng)建windows應(yīng)用程序

??? ②From1類的構(gòu)造函數(shù)中:

??????? public From1()

??????? {
??????????? InitializeComponent();

??????????? SetStyle(ControlStyles.Opaque,true);

??????????? Bounds = new Rectangle(0,0,500,300);

??????? }

??? ③給類添加一個(gè)OnPaint()方法:

??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Graphics g = e.Graphics;

??????????? int y = 0;

???????????

??????????? g.FillRectangle(Brushes.White, ClientRectangle);


??????????? //Draw left-justified text.

??????????? Rectangle rect = new Rectangle(0,y,400,Font.Height);

??????????? g.DrawRectangle(Pens.Blue, rect);

??????????? g.DrawString("This text is left justified.", Font, Brushes.Black, rect); //Font這個(gè)字體繼承了Control的Font屬性的中指定

???????

??????????? y += Font.Height +20;

???????????

??????????? //Draw right-justified text.

??????????? Font aFont = new Font("Arial", 16, FontStyles.Bold|FontStyle.Italic); //創(chuàng)建了Font的一個(gè)新實(shí)例

??????????? rect = new Rectangle(0,y,400,aFont.Height);

??????????? g.DrawRectangle(Pens.Blue, rect);


??????????? StringFromat sf = new StringFormat();? //創(chuàng)建StringFormat對(duì)象,以便繪制右對(duì)齊和居中的文本

??????????? sf.Alignment = StringAlignment.Far;??? //Far是指右對(duì)齊;Near是指左對(duì)齊

??????????? g.DrawString("This text is right justified.", aFont, Brushed.Blue, rect, sf);
??????????? y += aFont.Height + 20;

???????????

??????????? //Manually call Dispose()

??????????? aFont.Dispose()


??????????? //draw centered text.

??????????? Font cFont = new Font("Courier New", 12, FontStyle.Underline);

??????????? rect = new Rectangle(0,y,400,cFont.Height);

??????????? g.DrawRectangle(Pens.Blue, rect);

??????????? sf = new StringFormat();

??????????? sf.Alignment = StringAlignment.Center;

??????????? g.DrawString("This text is centered and underlined.", cFont, Brushes.Red, rect, sf);

??????????? y += cFont.Height + 20;


??????????? //Manually call Dispose().

??????????? cFont.Dispose();

???????????????

??????????? //Draw multiline text .
??????????? Font trFont = new Font("Times New Roman", 12);

??????????? rect = new Rectangle(0,y,400,trFont.Height*3);

??????????? g.DrawRectangle(Pens.Blue, rect);

??????????? String longString = "This text is much longer, and drawn";

??????????? longString += "into a rectangle that is higher than ";

??????????? longString += .......;

??????????? g.DrawString(longString, trFont, Brushes.Black, rect);


??????????? //Manually call Dispose()

??????????? trFont.Dispose();

??????? }????????
??????? GDI+和字體本身決定基線在什么位置,我們不能控制基線。

???????

________________
?21.使用圖像進(jìn)行繪制
??? 可以用圖像創(chuàng)建畫筆(TextureBrush),再繪制用該圖像填充的圖形。

??? 還可以從TextureBrush中創(chuàng)建鋼筆,使用圖像繪制線條。???

??? 在繪制文本時(shí),可以提供一個(gè)TextureBrush,就可以用圖像繪制文本了。

??? Image類在System.Drawing名稱空間中。


??? Image本身是一個(gè)抽象類,它有兩個(gè)子類:Bitmap和Metafile。

??? Bitmap類用于一般的圖像,有高度和寬度屬性。


??? 對(duì)于Image對(duì)象總是要調(diào)用Dispose().

???

??? 位圖有幾個(gè)來(lái)源:

??????? 可以從文件中加載位圖;

??????? 可以從另一個(gè)現(xiàn)有的圖像中創(chuàng)建位圖。

??? 位圖可以創(chuàng)建為空白圖像,以便在其上繪圖。

??? 在從文件中讀取圖像時(shí),該圖像可以是JPEG、GIF或BMP格式。


??? 例:

??? 讀取并繪制圖像

??? ①創(chuàng)建Windows應(yīng)用程序

??? ②添加一個(gè)Image私有對(duì)象,來(lái)保存圖像

??????? partial class Form1:Form
??????? {
??????????? private Image theImage;

??????? }

??? ③ 修改構(gòu)造函數(shù):

??????? public Form1()

??????? {
??????????? InitializeComponent();

??????????? SetStyle(ControlStyle.Opaque,true);

??????????? //需要把BMP文件Person.bmp放在Debug目錄下。才能用下面的語(yǔ)句。
??????????? //可以用其他位置的圖像,但要該代碼。

??????????? theImage? = new Bitmap("Person.bmp");
??????? }


??? ④ 給類添加OnPaintEvent()方法:

??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Graphics g = e.Graphics;
??????????? //在繪制圖像時(shí),把Rectangle作為一個(gè)參數(shù)傳遞給DrawImage()方法。

??????????? //如果圖像的大小與傳遞給DrawImage()的矩形不同,GDI+會(huì)自動(dòng)重新設(shè)置圖像大小。

??????????? //迫使GDI+不重新設(shè)置圖像大小的一種方式是從Width 和 Height屬性中獲取圖像的大小,再把圖像的大小傳遞給DrawImage()方法

??????????? g.DrawImage(theImage, ClientRectangle);

??????? }

??? ⑤ 最后,需要?jiǎng)h除存儲(chǔ)在類的一個(gè)成員變量中的Image。修改Form類的Dispose()方法。

??????? 注意,在VS2008中,Dispose()方法在Form1.Designer.cs中。
??????? protected override void Dispose(bool disposing)

??????? {
??????????? if(disposing)

??????????? {
??????????????? thdImage.Dispose();

??????????? }

??????????? if(disposing && (components != null ))

??????????? {
??????????????? components.Dispose();
??????????? }

??????????? base.Dispose(disposing);

??????? }

????????
??? 使用紋理畫筆繪圖
?? 下面用圖像創(chuàng)建一個(gè)TextureBrush,用該畫筆執(zhí)行3種不同的操作:
*???? 繪制橢圓
*???? 創(chuàng)建Pen
*???? 繪制文本
???

??? 例:

??? 用圖像繪制橢圓

??? ①給Form1類添加一個(gè)Image變量
??????? partial class Form1:Form

??????? {
??????????? private Image theImage;

??????????? private Image smallImage;
??????? }

??? ②在窗體構(gòu)造函數(shù)中,從theImage中創(chuàng)建一個(gè)smallImage。

??????? public Form1()

??????? {
??????????? InitializeComponent();

??????????? SetStyle(ControlStyle.Opaque, true);

??????????? theImage = new Bitmap("Person.bmp");
??????????? smallImage = new Bitmap(theImage, new Size(theImage.Width/2, theImage.Width/2, theImage.Height/2));

??????? }

??? ③用下面的代碼替換OnPaint()方法:
??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Graphics g = e.Graphics;

??????????? g.FillRectangle(Brushes.White, ClientRectangle);

??????????? Brush tBrush = new TextureBrush(smallImage , new Rectangle(0,0,smallImage.Width, smallImage.Height));


??????????? //調(diào)用Graphics類的FillEllipse()方法,傳遞新創(chuàng)建的紋理畫筆,ClientRectangle在窗口中繪制出橢圓

??????????? g.FillEllipse(tBrush, ClientRectangle);

??????????? tBrush.Dispose();

??????? }

??? ④最后,刪除變量中的兩個(gè)圖像。

??????? protected override void Dispose(bool disposing)

??????? {
??????????? if(disposing)

??????????? {
??????????????? theImage.Dispose();

??????????????? smallImage.Dispose();

??????????? }

??????????? if(disposing && (components != null))

??????????? {
??????????????? components.Dispose();

??????????? }
??????????? base.Dispose(disposing);

??????? }

??? 使用鋼筆繪制圖像
??? 例:

??? 在圖像中創(chuàng)建鋼筆

??? 修改OnPaint()方法:

??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Graphics g = e.Gragphics;

??????????? g.FillRectangle(Brushes.White, ClientRectangle);

??????????? Brush tBrush = new TextureBrush(smallImage, new Rectangle(0,0,smallImage.Width, smallImage.Height));

????????????
??????????? Pen tPen = new Pen(tBrush, 40);

??????????? g.DrawRectangle(tPen,0,0, ClientRectangle.Width, ClientRectangle.Height );

??????????? tPen.Dispose();

??????????? tBrush.Dispose();

??????? }


?? 用圖象繪制文本:

?? ① 修改OnPaint()方法:

??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Graphics g = e.Graphics;

??????????? g.FillRectangle(Brushes.White, ClientRectangle);

??????????? Brush tBrush = new TextureBrush(smallImage, new Rectangle(0,0,smallImage.Width, smallImage.Height));

??????????? Font trFont = new Font("Times new Roman", 32, FontStyle.Bold|FontStyle.Italic);

???????????

??????????? //調(diào)用DrawString()方法,參數(shù)是文本、字體、紋理畫筆 和 邊框矩形

??????????? g.DrawString("Hello from Beginning Visual C#" , trFont, tBrush, ClientRectangle);

??????????? tBrush.Dispose();

??????????? trFont.Dispose();

??????? }


??? 雙倍緩沖
??? 例:

??? ①不使用雙倍緩沖技術(shù)的程序
??????? 創(chuàng)建windows應(yīng)用程序,添加OnPaint()方法:

??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Graphics g = e.Graphics;

??????????? Random r = new Random();

??????????? g.FillRectangle(Brushes.White, ClientRectangle);

??????????? for(int x=0 ; x?ClientRectangle.Width ; x++)

??????????? {
??????????????? for(int y=0; y?ClientRectangle.Height; y += 10)

??????????????? {
??????????????????? Color C = Color.FromArgb(r.Next(255), r.Next(255), r.Next(255));

??????????????????? using (Pen p = new Pen(c,1))

??????????????????? {
??????????????????????? g.DrawLine(p,new Point(0,0), new Point(x,y));

??????????????????? }

??????????????? }

??????????? }

??????? }
????
??? ②使用雙倍緩沖
??????? protected override void OnPaint(PaintEventArgs e)

??????? {
??????????? Graphics displayGraphics = e.Graphics;

??????????? Random r = new Random();

??????????? //在雙倍緩沖的代碼中,創(chuàng)建高度和寬度與ClientRectangle相同的新圖像

??????????? Image i = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
??????????? //再使用下面的代碼從圖像中獲取一個(gè)Graphics對(duì)象

??????????? Graphics g = Graphics.FromImage(i);


??????????? g.FillRectangle(Brush.White, ClientRectangle);
????????????
??????????? for(int x=0; x?ClientRectangle.Width; x++)
??????????? {
??????????????? for(int y=0; y?ClientRectangle.Height; y+=10)

??????????????? {
??????????????????? // 靜態(tài)方法FromArgb(), 從3個(gè)指定的整數(shù)值中創(chuàng)建一個(gè)Color結(jié)構(gòu),對(duì)應(yīng)于顏色的紅、綠和藍(lán)色部分。

??????????????????? Color c = Color.FromArgb(r.Next(255), r.Next(255), r.Next(255));

??????????????????? Pen p = new Pen(c,1);

??????????????????? g.DrawLine(p, new Point(0,0), new Point(x,y));

??????????????????? p.Dispose();????????????????
??????????????? }???????????????
??????????? }??????
??????????? //把圖像繪制到窗口中

??????????? displayGraphics.DrawImage(i, ClientRectangle);
??????????? i.Dispose();????
??????? }

??????? 所有的圖像操作與前面的代碼一樣,但它們現(xiàn)在是繪制在圖像中,而不是直接繪制在窗口中。


________________

?22. GDI+高級(jí)功能介紹
??? 在調(diào)用OnPaint()方法時(shí),除了Graphics對(duì)象外,該方法傳遞了一個(gè)剪切矩形。
??? 如果實(shí)現(xiàn)一個(gè)非常精細(xì)的、需要很長(zhǎng)時(shí)間的繪圖歷程,在繪圖前測(cè)試一下這個(gè)剪切矩形,就可以減少繪圖時(shí)間。
??? 我們需要繪制任何圖形的邊框矩形。如果這個(gè)邊框矩形與剪切不相交,就可以跳過(guò)該繪圖操作。

??? 有時(shí),在繪制時(shí),如果需要繪制一個(gè)圖形的一部分,可以先繪制整個(gè)圖形,再把想要的部分剪切下來(lái)比較方便。
????
??? Graphics類的Clip屬性的更多信息參見(jiàn).net文檔

??? System.Drawing.Drawing2D
??? 這個(gè)名稱空間中的類提供了二維圖形 和 矢量圖形的高級(jí)功能。我們可以使用這些類建立復(fù)雜的圖形和圖像處理程序。
????
??? 這個(gè)空間包括:
*???? 高級(jí)畫筆??
?? * 前面介紹了LinearGradientBrush 和 PathGradientBrush,還有一個(gè)HatchBrush,它可以使用陰影線填充模式、前景色和背景色進(jìn)行繪制。
*???? Matrix類??
?? * 它定義了幾何變換。使用這個(gè)類可以變換繪圖操作,例如,使用Matrix類可以繪制傾斜的橢圓。
*???? GraphicsPath類??
?? * 前面已經(jīng)介紹過(guò)了。使用這個(gè)類可以定義復(fù)雜的路徑,一次繪制出整個(gè)路徑

??? System.Drawing.Imaging

??? 這個(gè)名稱空間中的類提供了高級(jí)的圖像支持。

??? System.Drawing.Imaging名稱空間類還可以擴(kuò)展GDI+,以支持其他圖像格式。
________________

總結(jié)

以上是生活随笔為你收集整理的C# 4的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。