程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> Visual Basic語言 >> VB.NET >> 使用My Extensibility擴展My命名空間

使用My Extensibility擴展My命名空間

編輯:VB.NET

目錄

擴展My命名空間的方法

使用單例擴展My

各種My擴展情形

編碼擴展

將擴展打包到一個模板中

作為模板的My擴展

.customdata文件

試試看!

在Visual Studio安裝程序文件中發布擴展

早在Visual Basic® 2005中,就通過引入My命名空間功能為常見編碼任務提供了快捷方法和API。從那以後,用戶已能夠編寫My命名空間擴展來輕松訪問自己的代碼庫。Visual Basic 2008中新提供的My Extensibility可使 My命名空間的擴展更加輕松。

有了新的My Extensibility 功能,可通過“項目屬性設計器”或者在對項目添加/刪除相關引用時,激活或停用My命名空間擴展。通過部署用於常見編碼任務的API,該功能使得擴展Visual Basic開發環境變得非常簡單。

在本節內容中,我將重點介紹如何使用My Extensibility 功能來集成擴展。如果希望了解有關如何編寫My命名空間實際代碼擴展的更多信息,請閱讀《MSDN® 雜志》2005 年 7 月刊的“通過自定義My命名空間來簡化常見任務”(http://msdn.microsoft.com/msdnmag/issues/05/07/My)。

擴展My命名空間的方法

可使用多個代碼模型來擴展My。先來介紹一下您已知道如何使用的最簡單的模型。實際上,向My命名空間添加任何內容與向任何其他命名空間添加內容非常類似。下面是最簡單的示例:

Namespace My.HandyStuffForMy
<Global.Microsoft.VisualBasic.HideModuleName()> _
Friend Module HandyStuffForMyModule
Sub Foo()
...
End Sub
Property Bar()
...
End Property
End Module
End Namespace

此代碼使名為Foo的sub和名為Bar的屬性出現在My命名空間中的HandyStuffForMy命名空間內。有以下兩個地方應注意:HideModuleName屬性和Module 上的Friend 訪問修飾符。HideModuleName屬性將禁止 Module 名稱顯示在IntelliSense®中。由於無需鍵入 Module 名稱來引用其成員,因此顯示 Module 只會使 IntelliSense 變得很散亂(請參見圖1)。

Figure 1Sub Namespace in IntelliSense

如果希望將這些成員直接添加到My 而不將它們放在一個子命名空間內(請參見圖2),只需將命名空間 My.HandyStuffForMy 更改為命名空間 My 即可,如下所示:

Namespace My
<Global.Microsoft.VisualBasic.HideModuleName()> _
Friend Module HandyStuffForMyModule
Sub Foo()
...
End Sub
Property Bar()
...
End Property
End Module
End Namespace

Figure 2No Sub Namespace

此外,如果使用My中已存在的命名空間(如 Resources),這些成員將添加到該命名空間中。因此,您可以非常靈活地控制擴展的訪問方式。需注意的第二個地方是Module 上的訪問修飾符。Friend 訪問修飾符將阻止其他程序集訪問這些成員。如果使用Public 訪問,則元素會與在此類其他項目的My命名空間中聲明的符號發生沖突。

我將使用我剛才提到的策略來建立 My擴展示例。但是,並非 My中的所有內容都是命名空間。還有返回特定類的全局實例的屬性,也稱為單例。

使用單例擴展My

My.Computer、My.Settings和My.Application 分別為名為My.MyComputer、My.MySettings和My.MyApplication的類的單例實例。可使用局部類功能輕松地將成員添加到這些類中。例如,以下代碼將名為Shutdown的sub 添加到My.Computer 對象中:

Namespace My
Partial Class MyComputer
Sub Shutdown()
...
End Sub
End Class
End Namespace

此代碼可用於擴展My.Application和My.Settings。只要該類的源代碼存在於當前項目中,就可利用局部類將成員添加到在其他某處定義的類中。它包括 Visual Basic項目中的MyComputer 這樣的類,因為編譯器會在編譯代碼之前自動插入類。

如果想要允許通過單例(就像 My.Computer、My.Settings和My.Application)訪問所添加的元素,但又希望創建自己的對象,那該怎麼辦呢?首先使用我在本專欄開頭所介紹的策略來向My命名空間添加一個ReadOnly屬性,然後讓該屬性返回 ThreadSafeObjectProvider(Of T) 類所提供的全局實例。與之前提到的新命名空間策略相比,此方法會針對每個線程生成一個新的類實例。圖3 顯示如何添加包含成員 Foo和Bar 且名為My.CustomMyObject的全局對象。圖4 顯示 IDE中產生的IntelliSense 體驗。

Figure3添加My.CustomMyObject

Namespace My
<Global.System.ComponentModel.EditorBrowsable _
(Global.System.ComponentModel.EditorBrowsableState.Never)> _
Partial Friend Class MyCustomMyObject
Public Sub Foo()
...
End Sub
Public Property Bar()
...
End Property
End Class
<Global.Microsoft.VisualBasic.HideModuleName()> _
Friend Module CustomMyObjectModule
Private instance As ThreadSafeObjectProvider(Of MyCustomMyObject)
ReadOnly Property CustomMyObject() As MyCustomMyObject
Get
Return instance.GetInstance()
End Get
End Property
End Module
End Namespace

Figure 4My.CustomMyObject in IntelliSense

各種 My擴展情形

擴展My.User可能是最難的情形。它是在項目之外的Visual Basic運行時DLL中定義的,即意味著無法使用局部類來擴展它。要擴展My.User,必須定義項目級編譯常量,即表示擴展My.User 需要使用擴展的開發人員執行這一手動步驟。

在任何情況下,如果需要擴展My.User的示例和指導,請參閱前面提到的《MSDN 雜志》文章,它還包含有關特定情形的信息,如擴展My.Application.Log、擴展My.Computer.Network 以及自定義My.Settings 存儲應用程序配置信息的方法。

那麼My.WebServices和My.Forms 這類對象又是怎樣的情形呢?這些對象的類是Module中定義的嵌套類型(即無法使用局部類功能來操作它們),並且它們為NotInheritable(即無法像 My.User 一樣擴展它們)。要向它們添加成員,並沒有簡便方法。此時,必須為擴展尋找一種更好的方法來配合 My命名空間。

編碼擴展

至此,我已介紹了My命名空間的擴展,讓我們來看看如何在項目中實現和共享這些擴展。我剛展示了My在哪些方面非常類似其他命名空間,因此可通過添加一個模塊並指定 My的一個命名空間來向它添加頂級屬性。現在,我們來創建一組驗證函數,用它們檢查字符串是否匹配美國和加拿大的郵政編碼、電話號碼、電子郵件地址的格式以及其他一些重要格式。

首先啟動Visual Studio® 並創建一個新的控制台應用程序。將項目命名為MyValidation。接下來,向名為MyValidation.vb的解決方案添加一個新模塊,並將MyValidation.vb文件中的代碼替換成圖5(鑒於篇幅有限,僅摘錄了其中一部分)中所示的代碼。

Figure5驗證代碼摘錄

Imports System.Text.RegularExpressions
Imports System
Imports System.Linq
Imports Microsoft.VisualBasic
Namespace My.Validation
<Global.Microsoft.VisualBasic.HideModuleName()> _
Public Module MyValidationMod
Public Function IsEmpty(ByVal value As Object) As Boolean
If (value Is Nothing) OrElse _
(value Is System.DBNull.Value) OrElse _
(value.ToString = String.Empty) OrElse _
(TypeOf value Is Date AndAlso CDate(value) = Date.MinValue) _
Then
Return True
Else
Return False
End If
End Function
Public Function IsAlphaNumeric(ByVal value As String, _
Optional ByVal emptyOK As Boolean = False, Optional ByVal _
whitespaceOK As Boolean = False) As Boolean
If IsEmpty(value) Then Return emptyOK
Dim expr As String
If whitespaceOK Then
expr = "^[a-zA-Z0-9s]+$"
Else
expr = "^[a-zA-Z0-9]+$"
End If
Return Regex.IsMatch(value, expr)
End Function
...
Public Function IsCanadianProvince(ByVal st As String) As Boolean
Dim allProv = "|AB|BC|MB|NB|NL|NT|NS|NU|ON|PE|QC|SK|YT"
Return st.Length = 2 AndAlso allProv.IndexOf("|" & st) <> -1
End Function
Public Function IsUSAState(ByRef st As String) As Boolean
Dim allStates = "|AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA|HI|ID|IL|IN|IA|" & _
"KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|" & _
"OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY"
Return st.Length = 2 AndAlso allStates.IndexOf("|" & st) <> -1
End Function
Public Function IsUSAPostalCode(ByVal zip As String) As Boolean
If String.IsNullOrEmpty(zip) Then Return False
Return Regex.IsMatch(zip, "^d{5}(-d{4})?$")
End Function
Public Function IsCanadianPostalCode(ByVal zip As String) As Boolean
If String.IsNullOrEmpty(zip) Then Return False
Return Regex.IsMatch(zip, "^[A-Z]d[A-Z] d[A-Z]d$")
End Function
Public Function IsNorthAmericanPhone(ByRef phone As String) As Boolean
If String.IsNullOrEmpty(phone) Then Return False
Dim expr As String = "^(?:([2-9]d{2}) ?|[2-9]d{2}" & _
"(?:-?| ?))[2-9]d{2}[- ]?d{4}$"
Return Regex.IsMatch(phone, expr)
End Function
Public Function IsEmail(ByRef email As String) As Boolean
If String.IsNullOrEmpty(email) Then Return False
Dim localPartCharset = "[0-9a-zA-Z!#$%*/?|^{}`~&'+-=_]"
Dim domainPartCharset = "[0-9a-zA-Z-]"
Dim expr = String.Format("^{0}+(.{0}+)*@{1}+(.{1}+)*", _
localPartCharset, domainPartCharset)
Return Regex.IsMatch(email, expr)
End Function
End Module
End Namespace

創建My擴展模板時請務必小心,代碼可用於任何項目配置。尤其需注意 Option Explicit、Option Strict、Option Compare和Option Infer(Visual Basic 2008中新引入)的可能值。您可編寫用於靈活性最小的配置(未指定 Option Explicit On、Option Strict On、Option Infer Off和Option Compare)的代碼,或者在擴展中的每個代碼文件的開頭明確指定每個選項(建議使用此方法)。

並且,需仔細考慮不同的項目導入,以防止與項目中定義的符號發生沖突。為此,使用Global或My 關鍵字來使未在模板中定義的所有符號符合要求。例如,不是使用Text.Encoding,而是使用Global.System.Text.Encoding。如果僅使用Text.Encoding,模板將無法用於 Windows® 窗體應用程序,此類程序會導入包含 Text命名空間的兩個命名空間。如果忽略 Global 且僅使用System.Text.Encoding,則模板將無法用於定義了System命名空間的項目。

在將代碼分發給他人之前徹底測試該代碼始終是個好習慣,My擴展也一樣。讓我們使用自動創建的模塊(Module1.vb)為My擴展編寫測試。在發現錯誤後再重新導出擴展會是件非常麻煩的事情,因此最好盡可能使擴展可正常運行並確保在首次導出它之前已對其進行了適當測試。

在“解決方案資源管理器”中雙擊 Module1.vb 將其打開,並將測試代碼(圖6中摘錄有其中一部分)放入文件中,替換掉之前該處的代碼。如需完整代碼,請參閱《MSDN 雜志》網站上的代碼下載。現在,您已做好測試 My擴展的准備,因此可按 F5 執行項目並附加調試程序。您會看到以下輸出:

Figure6測試代碼摘錄

Module Module1
Private testNumber As Integer
Private testGroup As String
Sub StartTestGroup(ByVal name As String)
testGroup = name
testNumber = 0
End Sub
Sub Test(ByVal result As Boolean, ByVal expected As Boolean)
testNumber += 1
If result <> expected Then
Console.WriteLine("Test #{0} of group {1} FAILED.", _
testNumber, testGroup)
End If
End Sub
Sub Main()
StartTestGroup("IsAlphaNumeric")
Test(My.Validation.IsAlphaNumeric("123HH2", True, True), True)
...
StartTestGroup("IsCanadianPostalCode")
Test(My.Validation.IsCanadianPostalCode("H0H 0H0"), True)
...
StartTestGroup("IsCanadianProvince")
Test(My.Validation.IsCanadianProvince("ON"), True)
...
StartTestGroup("IsEmail")
Test(My.Validation.IsEmail("[email protected]"), True)
...
Console.WriteLine _
("Tests are finished. No FAILED messages indicates success.")
Console.WriteLine("Press any key to continue.")
Console.ReadKey(True)
End Sub
End Module
Tests are finished. No FAILED messages indicates success.
Press any key to continue.

將擴展打包到一個模板中

擴展現已編寫並測試完畢,可以將它打包到My擴展模板中了。當項目處於打開狀態時,單擊“File”(文件)菜單,然後選擇“Export template...”(導出模板...)。如果“File”(文件)菜單中並無該選項,右鍵單擊工具欄並選擇“Customize”(自定義),選擇“Commands”(命令)選項卡,選擇“File”(文件)類別,然後將“Export Template”(導出模板)命令拖到“File”(文件)菜單上。導出模板時會出現“Export Template Wizard”(導出模板向導)。選擇“Item template”(項模板)(請參見圖7)。My擴展始終是項模板—決不會是項目模板。

Figure 7Choose Template Type

您可選擇將在其中創建模板的項目,在本解決方案中只有一個項目,因此只需單擊“Next”(下一步)。在“Items to Export”(導入項)列表框中,選擇MyValidation.vb文件並單擊“Next”(下一步)。在下一個步驟中,您可選擇要包括在該項中的參考。您必須選擇My擴展所需的所有參考,這樣將它添加到項目後才能正常運行。對於本示例,選擇System.Core,然後再次單擊“Next”(下一步)。

在最後一步中,填寫“Template Description”(模板說明)文本框,例如 "Extends the My namespace with a set of string validation methods"。最後,取消選中“Automatically import the template into Visual Studio”(自動將模板導入到Visual Studio中)。此設置可確保不會立即導入模板。在將模板用作 My擴展之前,需修改其中的一些內容,因此請單擊“Finish”(完成)。

作為模板的My擴展

在My擴展模板中(就像在任何 Visual Studio 模板中一樣),所有模板參數均可供使用。它們是在My擴展代碼添加到項目時會自動插入到其中的特殊字符串。例如,$clrversion$ 將被替換成 CLR的當前版本。 對於 My擴展模板而言,$safeitemname$ 將被替換成 .vstemplate文件中 <DefaultName>元素的值減去文件擴展名。它將等於包含模板代碼的.vb文件的名稱。

可對常規模板執行的所有其他操作也適用於 My擴展模板。例如,在.vstemplate文件中,通過將<Hidden>元素的值設置為false,在將項添加到項目中時可在“Add New Item”(添加新項)對話框中包括模板。還可使用<References> 部分來強制添加程序集引用,並且可像 Windows 窗體模板一樣添加一系列代碼文件以包括窗體的設計代碼和用戶代碼。

如需通過.vstemplate文件配置模板的更多信息,請參閱“MSDN 庫”中提供的“VSTemplate元素”參考,網址為http://go.microsoft.com/fwlink/?LinkId=110905。有關模板參數的更多信息,請參閱“Visual Studio 模板參數”文檔,網址為http://go.microsoft.com/fwlink/?LinkId=110907。

典型項模板與My Extensibility項模板之間存在許多主要差別。為啟用“項模板”以便可從 Visual Basic項目設計器的“My擴展”頁面對其進行管理,必須使用特殊步驟來正確配置它。

首先,需向導出的模板.zip文件中的MyTemplate.vstemplate文件添加<CustomDataSignature>元素。它表示將“項模板”視作 My擴展。您還需通過向<ProjectItem>元素添加兩個屬性來防止當模板添加到項目中時其中的項自動打開。這是因為使用者不應看到My擴展模板代碼。此外,必須將<Hidden>元素添加到MyTemplate.vstemplate中,以表示當用戶選擇通過“Add New Item”(添加新項)對話框將項添加到項目中時,已安裝模板列表中不應顯示該模板。最後,需向包中添加一個.customdata文件,以便提供沒有應用到典型模板的信息,即獨有 ID、版本號和觸發程序集。

為此,必須先解壓縮.zip文件,執行變更,然後重新打包必要的文件。因此,首先將模板的內容解壓到一個空目錄中,以便可對其進行編輯。Visual Studio 會將文件放在%MyDocs%Visual Studio 2008My Exported Templates中,其中 %MyDocs%為My Documents文件夾。

在文本或XML 編輯器中打開 MyTemplate.vstemplate文件,對圖8中以紅色突出顯示的部分進行編輯。請記住,XML與Visual Basic不同,它區分大小寫。

Figure8My Extensibility項模板

<VSTemplate Version="2.0.0"
xmlns=http://schemas.microsoft.com/developer/vstemplate/2005
Type="Item">
<TemplateData>
<DefaultName>MyValidation.vb</DefaultName>
<Name>MyValidation</Name>
<Description>Extends the My namespace with a set of string
validation methods.</Description>
<ProjectType>VisualBasic</ProjectType>
<SortOrder>10</SortOrder>
<Icon>TemplateIcon.ico</Icon>
<!-- Configures the template to not be shown as an option
when the user selects to add an item template to his project -->
<Hidden>true</Hidden>
<!-- Indicates it is to be treated as a My Extension. -->
<CustomDataSignature>Microsoft.VisualBasic.MyExtension
</CustomDataSignature>
</TemplateData>
<TemplateContent>
<References>
<Reference> <Assembly>System.Core</Assembly> </Reference>
</References>
<ProjectItem SubType="Code" TargetFileName="$fileinputname$.vb"
ReplaceParameters="true" OpenInEditor="false"
OpenInWebBrowser="false" OpenInHelpBrowser="false">MyValidation.vb
</ProjectItem>
</TemplateContent>
</VSTemplate>

創建將打包為.zip文件的一個新文件,名為MyValidation.customdata。請注意,以.customdata 結尾的任何文件均可以。在記事本或任意文本編輯器中,添加以下標記:

<VBMyExtensionTemplate
ID="MyValidationMyNamespaceExtension"
Version="1.0.0.0" />

在本示例中省略的AssemblyFullName屬性會指出哪個程序集將觸發My擴展。換句話說,可在此處指定:只要此程序集被添加到項目中,就會邀請用戶添加My擴展。只要從項目中刪除此程序集,並且 My擴展當時處於活動狀態,就會邀請用戶刪除My擴展。要指定觸發程序集(如 System.Windows.Forms),需將以下文本插入到.customdata文件中:

<VBMyExtensionTemplate
ID="MyValidationMyNamespaceExtension"
Version="1.0.0.0"
AssemblyFullName="System.Windows.Forms" />

現在,您已准備好將文件復制回模板.zip文件中。您可能想要編輯模板的圖標,但用戶是看不到My擴展模板圖標的,因此建議保留原樣。使用Windows資源管理器將四個文件復制回 .zip文件。然後,將.zip文件復制回 %MyDocs%Visual Studio 2008TemplatesItemTemplates,其中 %MyDocs%為My Documents文件夾。

.customdata文件

項目內 My擴展的處理在很大程度上是隱藏且自動進行的。為使 Visual Studio 能順利地處理這些文件並且幾乎不需要用戶輸入,以.vbproj為擴展名的項目文件擁有一些新屬性。如果在文本編輯器中打開了項目(添加了MyValidation擴展)的.vbproj文件,即可看到它們。您將看到如下代碼:

<ItemGroup>
...
<Compile Include="My ProjectMyExtensionsMyValidation.vb">
<VBMyExtensionTemplateID>
MyValidationMyNamespaceExtension
</VBMyExtensionTemplateID>
<VBMyExtensionTemplateVersion>
1.0.0.0
</VBMyExtensionTemplateVersion>
</Compile>
...
</ItemGroup>

但是,如果查看普通代碼文件(如 Module1.vb)的條目,則僅會看到:

<ItemGroup>
<Compile Include="Module1.vb" />
</ItemGroup>

正如您所看到的,這裡存在一些差別。首先,MyValidation.vb文件存儲在My Project文件夾中,即意味著除非用戶按“解決方案資源管理器”中的“Show All Items”(顯示所有項)按鈕,否則他們是看不到此文件的。此外,MyValidation.vb文件有兩組額外的元數據,與MyValidation.customdata文件中添加的值相對應。

該信息存儲在此處後,Visual Studio允許用戶通過“My Extensions Project Designer”(My擴展項目設計器)選項卡添加和刪除擴展,而不是直接添加或刪除文件。此外,如果刪除了對觸發程序集的引用,Visual Studio 會警告用戶 My擴展可能會停止工作並提示您刪除模板。該信息還使 Visual Studio 可防止在同一項目中出現兩個擴展副本。

試試看!

My擴展現已做好在My Extensibility 功能中集成使用的准備。要使用它,首先啟動Visual Studio的一個新實例並創建一個新項目。然後,通過右鍵單擊該項目並選擇“Properties”(屬性)或雙擊“解決方案資源管理器”中的My Project,打開“Project Designer”(項目設計器)。在“My Extensions”(My擴展)選項卡上,單擊“Add Extension”(添加擴展)並選擇剛創建的模板,然後單擊“OK”(確定)。此時,擴展即已加載到項目中。如果在代碼中鍵入 My.(注意圓點),您將會看到Validation 是可通過IntelliSense 使用的一個命名空間。

在Visual Studio安裝程序文件中發布擴展

為了更加輕松地將擴展分發給其他開發人員,可創建一個安裝程序文件。Visual Studio安裝程序文件是一個重命名後包含擴展名.vsi的.zip文件。文件包含 Visual Studio 加載項和用於介紹它的.vscontent文件。讓我們通過示例來進一步論述,並為My擴展創建一個.vsi文件。首先,創建一個名為MyValidation.vscontent、包含圖9中文本的文本文件來介紹內容。

Figure9MyValidation安裝程序

<VSContent xmlns="http://schemas.microsoft.com/developer/vscontent/2005">
<Content>
<FileName>MyValidation.zip</FileName>
<DisplayName>My.Validation Extension</DisplayName>
<Description>Extends the My namespace with a set of string
validation methods.</Description>
<FileContentType>VSTemplate</FileContentType>
<ContentVersion>1.0</ContentVersion>
<Attributes>
<Attribute name="TemplateType" value="Item"/>
</Attributes>
</Content>
</VSContent>

如果創建另一個My擴展,可能需要更改的元素僅是FileName、DisplayName、Description和ContentVersion 值。如需創建Visual Studio安裝程序文件的更多信息以及這些元素的詳細解釋,請參閱http://go.microsoft.com/fwlink/?LinkId=110908上的“MSDN 庫”主題。

將該 MyValidation.vscontent和MyValidation.zip文件放到名為MyValidationInstall.zip的另一個.zip文件中。然後,將MyValidationInstall.zip 重命名為MyValidationInstall.vsi。現在,只需雙擊它即可自動將模板安裝到Visual Studio中。請注意,如果已存在具有相同名稱的模板,系統會提示您將覆蓋該模板。如果您已清楚會實際發生的情況,則覆蓋文件即可。現在您可以分發該 .vsi文件,通過它將My擴展輕松地安裝到其他開發人員的機器上。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved