第六章 高級編程
1.特性(特征)
特性(attribute)是一種允許我們向程序的程序集添加元數據的語言結構.它是用于保存程序結構信息的某種特殊類型的類.
特性提供功能強大的方法,用以將元數據或聲明信息與代碼(程序集、類型、方法、屬性等)相關聯。特性與程序實體關聯后,
即可在運行時使用名為“反射”的技術查詢特性。
將應用了特性的程序結構叫做目標.
設計用來獲取和使用元數據的程序(對象瀏覽器)叫做特性的消費者
.NET預定了很多特性,我們也可以聲明自定義特性.
Obsolete特性(方法前):
可以使用Obsolete特性將程序結構標注為過期的,并且在代碼編譯時,顯示警告信息.
格式:[ Obsolete( "警告信息", true)]//最后一個參數為true表示這個方法不能被調用了,如果調用則出錯
Conditional特性(方法前):
為方法聲明應用Conditional特性并把編譯符作為參數來使用
是否屏蔽特定方法的調用,如果參數的字符串定義了宏則調用,如果沒有定義則不調用
System.Diagnostics;//所需命名空間
格式: # define hong //如果定義了宏則調用,如果沒有定義則不調用(宏聲明在最外層).
[ Conditional ( "hong" )]
在方法上使用Conditional特性的規則:
【1】該方法必須是類或結構體的方法;
【2】該方法必須為void類型;
【3】該方法不能被聲明為override,但可以標記為virtual;
【4】該方法不能是接口方法的實現。
DebuggerStepThrough特性(方法前)
可以跳過Debugger的單步調試,不讓進入該方法的調試(當我們確定這個方法沒有任何錯誤的時候,可以使用這個)
格式:[ DebuggerStepThrough ]
調用者信息特性(參數前):
using System.Runtime.CompilerServices;//導入命名空間
[ CallerFilePath ]:調用者的文件路徑
[ CallerLineNumber ]:調用者代碼行數
[ CallerMemberName ]:調用者成員或方法名稱
//如果調用方法時顯式指定了這些參數,則使用真正的參數值;如果沒有顯式提供參數值,則系統將會提供文件路徑、代碼行數、方法成員名稱。
(其他特性)
[ CLSCompliant ]:聲明可公開的成員應該被編譯器檢查是否符合CLS.兼容的程序集可以被任何.NET兼容的語言使用
[ Serializable] :聲明結構可以被序列化.
[ NonSerialized ]:聲明結構不可以被序列化
[ DLLImport ]:聲明是非托管代碼實現的.
[ WebMethod ]:聲明方法應該被作為XML Web服務的一部分暴露
[ AttributeUsage ]:聲明特性能應用到什么類型的程序結構.將這個特性應用到特性聲明上.
自定義特性的規范:
命名規范:特性名使用Pascal命名法(首字母大寫),并且以Attribute后綴結尾,當為目標應用特性時,我們可以不使用后綴。
例如對于SerializableAttrbute和MyAttributeAttribute這兩個特性,我們把他們應用到結構是可以使用Serializable和MyAttribute。
定義:
1)特性類后綴以Attribute結尾
2)需要繼承于System.Attribute
3)特性類是不需要被繼承的,一般聲明為sealed
4)一般情況下特性類用來表示目標結構的一些狀態(只定義一些字段或屬性,一般不定義方法)
定義或控制特性的使用:
AttributeUsage類是另外一個預定義特性類,它幫助我們控制我們自己的定制特性的使用。它描述了一個定制特性如和被使用。
AttributeUsage有三個屬性,我們可以把它放置在定制屬性前面。
ValidOn
通過這個屬性,我們能夠定義定制特性應該在何種程序實體前放置。一個屬性可以被放置的所有程序實體在AttributeTargets enumerator中列出。
通過OR操作我們可以把若干個AttributeTargets值組合起來。 我們可以使用AttributeTargets.All來允許特性被放置在任何程序實體前。
AllowMultiple
這個屬性標記了我們的定制特性能否被重復放置在同一個程序實體前多次。
Inherited
我們可以使用這個屬性來控制定制特性的繼承規則。表明當特性被放置在一個基類上時,基類的這個特性能否被派生類所繼承。
一個聲明上可放置多個特性;某些特性對于給定實體可以指定多次。
例如,ConditionalAttribute 就是一個可多次使用的特性:[Conditional("DEBUG"), Conditional("TEST1")]
例:
//表示該特性類可以應用于哪些程序結構 這里表示應用于類,不可在程序實體前使用多次,基類該特性不可被繼承
[ AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class MytestAtrribute:System.Attribute
{
public string Description{get; set;} //屬性
public string VersionNumber{get; set;}
public string ReviewerID{get; set;}
//除了屬性外,不可實現公有方法或其他函數成員
public MytestAtrribute(string desc,string ver) //構造函數
{
Description = desc;
VersionNumber = ver;
}
}
[Mytest( "? ? ?")] //將括在方括號中的特性名置于其應用到的實體的聲明上方
class Program
{
****
}
詳細:https://blog.csdn.net/c38623862/article/details/65443975
https://www.cnblogs.com/liuxinxin/articles/2265672.html
https://www.cnblogs.com/rohelm/archive/2012/04/19/2456088.html
訪問特性:
【1】使用IsDefined方法
可以使用Type對象的IsDefined方法來檢測某個特性是否應用到了某個類上。
MyClass mc = new MyClass(); //創建類的對象
Type t = mc.GetType();//使用從Object基類繼承的GetType方法獲取Type對象的一個引用
bool isDefined = t.IsDefined(typeof(MytestAtrribute),false); //調用IsDefined方法來判斷特性是否應用在了這個類上
//第一個參數:接受需要檢查的特性的Type對象
//第二個參數:bool類型,指示是否搜索該類的繼承樹來查找這個特性
【2】使用GetCustomAttribute方法
Type類的GetCustomAttribute方法返回應用到結構上的特性的數組。
Type t = typeof(MyClass);
object[] attr = t.GetCustomAttribute(false);//布爾參數指定是否搜索該類的繼承樹來查找這個特性
foreach(Attribute ar in attr)
{
MytestAtrribute attrl = (MytestAtrribute)ar;//實際返回的對象是object數組,必須強制轉換為相應的特性類型
}
2.元數據
元數據是有關程序及其類型的數據。
是一種二進制信息,用以對存儲在公共語言運行庫可移植可執行文件 (PE) 文件或存儲在內存中的程序進行描述。將您的代碼編譯為 PE 文件時,便會將元數據插入到該文件的一部分中,而將代碼轉換為 Microsoft中間語言(MSIL)并將其插入到該文件的另一部分中。
在模塊或程序集中定義和引用的每個類型和成員都將在元數據中進行說明。當執行代碼時,運行庫將元數據加載到內存中,
并引用它來發現有關代碼的類、成員、繼承等信息。
詳細:https://www.cnblogs.com/Peter-Luo/archive/2012/05/31/2528889.html
3.反射
運行中的程序查看本身的元數據或其他程序的元數據的行為叫作反射。使用反射,必須使用System.Reflection命名空間。
這是.Net中獲取運行時類型信息的方式,.Net的應用程序由幾個部分:‘程序集(Assembly)’、‘模塊(Module)’、‘類型(class)’組成,而反射提供一種編程的方式,讓程序員可以在程序運行期獲得這幾個組成部分的相關信息,例如:
(1)使用Assembly定義和加載程序集,加載在程序集清單中列出模塊,以及從此程序集中查找類型并創建該類型的實例。?
(2)使用Module了解包含模塊的程序集以及模塊中的類等,還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法。?
(3)使用ConstructorInfo了解構造函數的名稱、參數、訪問修飾符(如pulic 或private)和實現詳細信息(如abstract或virtual)等。?
(4)使用MethodInfo了解方法的名稱、返回類型、參數、訪問修飾符(如pulic 或private)和實現詳細信息(如abstract或virtual)等。
(5)使用FiedInfo了解字段的名稱、訪問修飾符(如public或private)和實現詳細信息(如static)等,并獲取或設置字段值。
(6)使用EventInfo了解事件的名稱、事件處理程序數據類型、自定義屬性、聲明類型和反射類型等,添加或移除事件處理程序。?
(7)使用PropertyInfo了解屬性的名稱、數據類型、聲明類型、反射類型和只讀或可寫狀態等,獲取或設置屬性值。?
(8)使用ParameterInfo了解參數的名稱、數據類型、是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。
【1】反射的作用:
1)可以使用反射動態地創建類型的實例,將類型綁定到現有對象,或從現有對象中獲取類型
2)應用程序需要在運行時從某個特定的程序集中載入一個特定的類型,以便實現某個任務時可以用到反射。
3)反射主要應用于類庫,這些類庫需要知道一個類型的定義,以便提供更多的功能。
【2】有3種獲取給定類型的type引用:
1. Type t = typeog(string);
2. string s = "grayworm";
? ? Type t = s.GetType();
3. Type t = Type.GetType("system.string");
【3】Type類方法:
? ? GetConstructor(), GetConstructors() //返回ConstructorInfo類型,用于取得該類的構造函數的信息
? ? GetEvent(), GetEvents()? //返回EventInfo類型,用于取得該類的事件的信息
? ? GetField(), GetFields()? //返回FieldInfo類型,用于取得該類的字段(成員變量)的信息
? ? GetInterface(), GetInterfaces()? //返回InterfaceInfo類型,用于取得該類實現的接口的信息
? ? GetMember(), GetMembers()? //返回MemberInfo類型,用于取得該類的所有成員的信息
? ? GetMethod(), GetMethods()? //返回MethodInfo類型,用于取得該類的方法的信息
? ? GetProperty(), GetProperties()? //返回PropertyInfo類型,用于取得該類的屬性的信息
NewClassw nc = new NewClassw(); Type t = nc.GetType(); ConstructorInfo[] ci = t.GetConstructors(); //獲取類的所有構造函數 foreach (ConstructorInfo c in ci) //遍歷每一個構造函數 { ParameterInfo[] ps = c.GetParameters(); //取出每個構造函數的所有參數 foreach (ParameterInfo pi in ps) //遍歷并打印所該構造函數的所有參數 { Console.Write(pi.ParameterType.ToString()+" "+pi.Name+","); } console.writeline(); }
??【4】用反射生成對象,并調用屬性、方法和字段進行操作??
NewClassw nc = new NewClassw(); Type t = nc.GetType(); object obj = Activator.CreateInstance(t); //取得ID字段 FieldInfo fi = t.GetField("ID"); //給ID字段賦值 fi.SetValue(obj, "k001"); //取得MyName屬性 PropertyInfo pi1 = t.GetProperty("MyName"); //給MyName屬性賦值 pi1.SetValue(obj, "grayworm", null); PropertyInfo pi2 = t.GetProperty("MyInfo"); pi2.SetValue(obj, "hi.baidu.com/grayworm", null); //取得show方法 MethodInfo mi = t.GetMethod("show"); //調用show方法 mi.Invoke(obj, null);
【5】System.Reflection.Assembly類
? ? 通過程序集名稱返回Assembly對象
??????? Assembly ass = Assembly.Load("ClassLibrary831");
??? 通過DLL文件名稱返回Assembly對象
??????? Assembly ass = Assembly.LoadFrom("ClassLibrary831.dll");
??? 通過Assembly獲取程序集中類?
??????? Type t = ass.GetType("ClassLibrary831.NewClass");?? //參數必須是類的全名
??? 通過Assembly獲取程序集中所有的類
??????? Type[] t = ass.GetTypes();
詳細:
https://www.cnblogs.com/Stephenchao/p/4481995.html
https://www.cnblogs.com/vaevvaev/p/6995639.html
https://www.cnblogs.com/yaozhenfa/p/CSharp_Reflection_1.html
4.文件及數據流
文件:一些具有永久存儲及特定順序的字節組成的一個有序的、具有名稱的集合。
流:提供一種向后備存儲寫入字節和從后備存儲讀取字節的方式。
1)File類
支持對文件的基本操作,包括用于創建、復制、刪除、移動和打開文件的靜態方法,并協助創建FileStream對象。
Copy //將現有文件復制到新文件
Create //在指定路徑中創建文件
delete //刪除指定文件,若指定文件不存在,則不引發異常
Exists //確定指定文件是否存在
Move //將指定文件移動到新位置,并提供指定新文件名的選項
Open //打開指定路徑上的FileStream
GetCreationTime //返回指定文件或目錄的創建日期和時間
GetLastAccessTime //返回上次訪問文件或目錄的日期和時間
GetLastWriteTime //返回上傳寫入指定文件或目錄的日期和時間
OpenRead //打開現有文件進行讀取
OpenWrite //打開現有文件進行寫入
replace //使用其他文件的內容替換指定文件的內容,這一過程將刪除原始文件,并創建被替換文件的備份
//使用File類進行文件操作 class Program { static void Main(string[] args) { //在D盤下創建code文件夾 Directory.CreateDirectory("D:\\code"); Directory.CreateDirectory("D:\\code-1"); string path = "D:\\code\\test1.txt"; //創建文件 FileStream fs = File.Create(path); File.WriteAllText("D:\\code\\test1.txt", "qwertyuiop", System.Text.Encoding.UTF8); File.ReadAllText(path, System.Text.Encoding.UTF8); //獲取文件信息 Console.WriteLine("文件創建時間:" + File.GetCreationTime(path)); Console.WriteLine("文件最后被寫入時間:" + File.GetLastWriteTime(path)); //關閉文件流 fs.Close(); //設置目標路徑 string newPath = "D:\\code-1\\test1.txt"; //判斷目標文件是否存在 bool flag = File.Exists(newPath); if (flag) { //刪除文件 File.delete(newPath); } File.Move(path, newPath); } }
2)Directory類
CreatDirectory//創建文件夾
delete//刪除文件夾
//使用Directory類創建和刪除文件夾 class Program { static void Main(string[] args) { bool flag = Directory.Exists("D:\\code"); if (flag) { Directory.delete("D:\\code", true); } else { Directory.CreateDirectory("D:\\code"); } } }
3)數據流
在此主要講FileStream(文件流)的使用
常用屬性:
CanRead//獲取一個值,該值指示當前流是否支持讀取
CanWrite//獲取一個值,該值指示當前流是否支持寫入
CanSeek//獲取一個值,該值指示當前流是否支持查找
CanTimeout//獲取一個值,該值指示當前流是否可以超時
IsAsync//獲取一個值,該值指示文件流是異步還是同步打開
Length//獲取用字節表示的流長度
Name//獲取傳遞給構造函數的文件流的名稱
Position//獲取或設置此流的當前位置
ReadTimeout//獲取或設置一個值,該值確定流在超時前嘗試讀取多長時間
WriteTimeout//獲取或設置一個值,該值確定流在超時前嘗試寫入多長時間
常用方法:
BeginRead//開始異步讀操作
BeginWrite//開始異步寫操作
Close//關閉當前流并釋放與之關聯的所有資源
EndRead//等待掛起的異步讀取完成
EndWrite//結束異步寫入,在I/O操作完成之前一直阻止
Lock//允許讀取訪問的同時防止其他進程更改文件流
UnLock//允許其他進程訪問以前鎖定的某個文件的全部或部分
Read//從流中讀取字節塊并將該數據寫入給定的緩沖區中
Write//使用從緩沖區讀取的數據將字節塊寫入該流
ReadByte//從文件中讀取一個字節,并將讀取的位置提升一個字節
WriteByte//將一個字節寫入文件流的當前位置
Seek//將流的當前位置設置為給定值
SetLength//將該流的長度設置為給定值
FileMode類的枚舉成員:
Append//打開現有文件并查找到文件尾,只能同FileAccess.Write一起使用
Create//指定操作系統創建新的文件,如果文件已存在,則被改寫
CreateNew//指定操作系統創建新的文件,如果文件已存在,則引發IOException
Open//指定操作系統打開現有文件。打開文件的能力取決于FileAccess的值
OpenOrCreate//指定操作系統創建新的文件,如果文件已存在,否則應創建新文件
truncate//指定操作系統打開現有文件,文件一旦打開,就將被截斷為零字節大小
文本文件的寫入與讀取
[1]StreamWriter類
屬性:
Encoding//獲取將輸出寫入其中的Encoding中
Formatprovider//獲取控制格式設置的對象
NewLine//獲取或設置由當前TextWriter使用的行結束符字符串
方法:
Close//關閉當前的StringWriter和基礎流
Write//寫入StringWriter的此實例中
WriteLine//寫入重載參數指定的某些數據,后面跟行結束符
//StreamWriter類的使用 class Program { static void Main(string[] args) { string path = @"D:\\code\\test.txt"; //創建StreamWriter 類的實例 StreamWriter streamWriter = new StreamWriter(path); //向文件中寫入姓名 streamWriter.WriteLine("小張"); //向文件中寫入手機號 streamWriter.WriteLine("13112345678"); //刷新緩存 streamWriter.Flush(); //關閉流 streamWriter.Close(); } }
[2]StreamReader類
方法:
Close//關閉StringReader
Read//讀取輸入字符串中的下一個字符或下一組字符
ReadBlock//從當前流中讀取最大count的字符并從index開始將該數據寫入buffer
ReadLine//從基礎字符串中讀取一行
ReadToEnd//將整個流或從流的當前位置到流的結尾作為字符串讀取
//StreamReader 類的應用 class Program { static void Main(string[] args) { //定義文件路徑 string path = @"D:\\code\\test.txt"; //創建 StreamReader 類的實例 StreamReader streamReader = new StreamReader(path); //判斷文件中是否有字符 while (streamReader.Peek() != -1) { //讀取文件中的一行字符 string str = streamReader.ReadLine(); Console.WriteLine(str); } streamReader.Close(); } }
二進制文件的寫入與讀取
[1]BinaryWriter類
方法:
Close//關閉當前的BinaryWriter和基礎流
Seek//設置當前流的位置
Write//將值寫入當前流
[2]BinaryReader類
方法:
Close//關閉當前閱讀器及基礎流
PeekChar//返回一個可用字符,并且不提升字節或字符的位置
Read//從基礎流中讀取字符,并提升流的當前位置
ReadBoolean//從當前流中讀取Boolean值,并使該流當前位置提升一個字節
ReadByte//從當前流中讀取下一個字節,并使當前位置提升一個字節
ReadBytes//從當前流中讀取count個字節放入字節數組,并使當前位置提升count個字節
ReadChar//從當前流中讀取下一個字符,并根據所使用的Encoding和從流中讀取特定的字符,提升流當前的位置
ReadChars//從當前流中讀取count個字符,以字符數組形式返回數據,并根據所使用的Encoding和從流中讀取特定的字符,提升流當前的位置
ReadInt32//從當前流中讀取4個字節有符號整數,并使流的當前位置提升4個字節
ReadString//從當前流中讀取一個字符串,字符串有長度前綴,一次將7位編碼為整數
版本控制軟件:Git VSS TFS SVN
4)Git
https://docs.microsoft.com/zh-cn/visualstudio/version-control/git-with-visual-studio?view=vs-2019
5)VSS
Visual Source Safe,簡稱VSS。它提供了還原點和并行協作功能,從而使應用程序開發組織能夠同時處理軟件的多個版本。
該版本控制系統引入了簽入和簽出模型,按照該模型,單個開發人員可以簽出文件,進行修改,然后重新簽入該文件。當文件被簽出后,
其他開發人員通常無法對該文件進行更改。通過源代碼管理系統,開發人員還能夠回滾或撤消任何隨后產生問題的更改。
作為一種版本控制系統,Visual Source Safe 能夠:
? 防止用戶無意中丟失文件。
? 允許回溯到以前版本的文件。
? 允許分支、共享、合并和管理文件版本。
? 跟蹤整個項目的版本。
? 跟蹤模塊化代碼(一個由多個項目重用或共享的文件)。
https://blog.csdn.net/buknow/article/details/82841603
6)NuGet引用第三方庫
https://www.cnblogs.com/dathlin/p/7705014.html
7)利用反射實現一個工廠類
https://blog.csdn.net/silangquan/article/details/51100823
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
北京西單大悅城在幾環 西單大悅城什么時候關門?西單大悅城賣衣服嗎? 西單大悅城營業時間:10:00-22:00 西單歡樂城地址:君泰百貨北側,西單北街131號位于西單商業區中心,南側距長安街不足200米,北側連接金融街和新街口特色商業區。 行車路線:連接多條主要交通干線。北京地鐵1號線至西單站A出口周圍有25條公交線路。 以上是西單歡樂城什么時候營業時間的介紹。相信大家都已經知道了,希望...
歪歪如何設置鮮花?斜置花的方法如下:1。當等級達到16級時,可以送出一束鮮花。在我的花里,你可以設定一束花的數目。2. 渠道經理可以根據當前渠道刷花的情況,禁止送花或調整花的大小?;ǖ拇笮〔煌簑aiwai voice是廣州多灣信息技術有限公司開發的基于互聯網的團隊語音通信平臺,是一款功能強大、音質清晰、安全穩定、不占用資源、適合游戲玩家的免費語音軟件。在網絡上通常用YY來表示。簡而言之,它是一種...
推薦下,適合老年人做鈴聲~?根據老年人的愛好,適合中老年人的鈴聲可以分為:1.紅歌很多老人都經歷過紅色年代,對那個年代有一些回憶和懷念。而紅歌恰恰可以成為他們的最愛?!侗本┑慕鹕缴稀?、《黃河大合唱》等等。2.歌劇很多老年人愛聽歌劇,選擇歌劇作為鈴聲也是不錯的選擇?!赌鹿鹩鞄洝?、《紅燈記》、《小蒼娃》等經典京劇劇目也是不錯的選擇。3.最后浪漫的歌甚至兒歌《天涯歌女》、《四季歌》、《北風吹》、《我們...