轉帖|其它|編輯:郝浩|2010-10-28 14:34:41.000|閱讀 745 次
概述:C#中.我們可以利用部分類,將一個類分散到多個類文件中,這樣我們就可以多個開發者同時開發某個類庫,或者是擴展其他開發者發布的類庫.甚至是代碼生成器生成的代碼,例如LINQ2SQL,ADO.NET EF等,以獲取更高效的開發.
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
什么是部分類(Partial Class)?
C#中.我們可以利用部分類,將一個類分散到多個類文件中,這樣我們就可以多個開發者同時開發某個類庫,或者是擴展其他開發者發布的類庫.甚至是代碼生成器生成的代碼,例如LINQ2SQL,ADO.NET EF等,以獲取更高效的開發.
Re:Class和Class File的區別.這里的類是我們平時所說的普通類-Class,如抽象類,基類,子類等等.而類文件-Class File則是我們平時編寫類時所用到的文件,如C#的.cs,VB的.vb.
雖然部分類很好的解決了多個開發者同時開發而互不影響的問題,但其約束十分嚴格.開發者之間不能/很難彼此溝通,并且無法/很難修改對方的代碼.這意味著需要為對方提供很多掛鉤.這些掛鉤應該以部分方法的方式實現.而另一方的開發者可以選擇實現或不實現.
擴展現有類
實體框架的出現,大大的減輕了我們的工作量,使我們把更多的重心放在邏輯實現上,而減少對于數據訪問的關注.例如我們可以使用LINQ2SQL,LINQ2SQL是一個輕型的實體框架.它生成了我們對數據層的訪問.但.有些時候,我們需要擴展些自己的內容,如方法/屬性等等.除了直接在生成的類文件中添加修改意外,我們還可以利用部分類擴展我們所需的功能,前者當每次我們跟新實體時.你所擴展的內容都會消失.而部分類依然能很好的為你服務.
提供部分方法
為部分類提供最有效的鉤子就是部分方法.它和接口的方法聲明很相似.
關鍵字partial+void+方法名+方法參數.
partial void ReportValueChanging(RequestChange args);
由于部分方法可能成為類的一部分(實現),也可能不成為類的一部分(不實現),所以C#本身對于部分方法給出了一些限制.
1.返回類型必須為void.
2.部分方法不能為抽象/虛方法.
3.部分方法不能用來實現接口.
4.參數列表不能包含任何out參數,因為編譯器無法初始化這些out參數.
我們利用部分方法來讓用戶件事或修改類的行為:修改方法,事件處理程序及構造函數.
修改方法
修改方法是指那些將要修改類中對外可見的狀態的方法.我們可以將其理解為任何狀態的變化,由于另一個類文件的部分類實現依然是類的一部分.所以我們可以完全控制到該類的所有內部狀態.
一般而言,修改方法應該為類提供兩個部分方法.第一個在修改前調用,用來讓另一方(另一開發者)能夠進行合法性驗證等等.第二個方法應該在修改狀態后調用,用來讓另一方相應這個狀態的變化.
public partial class GeneratedStuff { private struct ReportChange { public readonly int OldValue; public readonly int NewValue; public ReportChange(int oldValue, int newValue) { this.OldValue = oldValue; this.NewValue = newValue; } } private class RequestChange { public ReportChange Values { get; set; } public bool Cancel { get; set; } } partial void ReportValueChanging(RequestChange args); partial void ReportValueChanged(ReportChange values); private int storage = 0; public void UpdateValue(int newValue) { RequestChange updateArgs = new RequestChange { Values = new ReportChange(storage, newValue) }; ReportValueChanging(updateArgs); if (!updateArgs.Cancel) { storage = newValue; ReportValueChanged(new ReportChange(storage, newValue)); } } }
如果另一個部分類沒有提供兩個部分方法的實現,那么C#編譯器將移除該調用.生成方法如下
public void UpdateValue(int newValue) { RequestChange updateArgs = new RequestChange { Values = new ReportChange(this.storage, newValue) }; if (!updateArgs.Cancel) { this.storage = newValue; } }
并且,兩個部分方法也一并移除了.
我們可以實現掛鉤如下
public partial class GeneratedStuff { partial void ReportValueChanging(GeneratedStuff.RequestChange args) { if (args.Values.NewValue < 0) { //dosomething... } else { //dosomething... } } partial void ReportValueChanged(GeneratedStuff.ReportChange values) { //dosomething... } }
這里,我們通過一個取消標記來讓開發者可以取消某個修改動作,你也可以通過拋出異常得到同樣的效果.但.推薦使用布爾型的取消標記,因為這樣更加輕量一些
事件處理程序
實際上,事件的處理程序和上面的方法修改并無多大的區別.你所需要做的.僅僅只是添加一個委托事件而已.實現了類似控件的事件機制.
構造函數擴展
無論是生成的代碼,還是我們手工編寫的代碼.我們都無法預計調用類時外部將會調用哪個構造函數.所以.我們只能在內部做一些手腳.例如
public partial class GeneratedStuff
{
partial void Initialize();
public GeneratedStuff() :
this(0)
{ }
public GeneratedStuff(int someValue)
{ this.storage = someValue; Initialize();
}
}
注意!Initialize在最后調用,這樣就有了一次檢查當前對象狀態的機會,可以進行必要的修改,或是對于不符合要求時拋出異常等等.實際上.這種構造函數重載也有效的提升你的代碼質量(對于不同的構造函數,結果IL都會生成不同的函數塊.而這種重構法最后其實真正生成的函數塊只有一個)
尾聲
經過以上的闡述,相信我們已經更了解部分類是怎樣煉成的了.只有更好的了解其背后的一系列"小動作",才有助于我們更好的提升,寫出更有質量的代碼
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:網絡轉載