標籤:預留位置 執行 csharp cti generics 靈活 methods sig img
看過的相當不錯的一篇文章,但是對基架還時不太理解,大神們看到,希望指點一二,能告訴點學習資源就更好了!
本篇文章不是出自本人之手,轉載完全處於膜拜以及學習!
歡迎加我:jkxx123321 備忘部落格加就可以了!
最近由於需要在架構中提供一些自訂模板的功能,找到了一篇部落格,可惜似乎是翻譯工具直接翻的,讀不通順,就試著自己翻譯下,我不會完全翻譯原文的句子,可能會對原文進行小範圍的我認為更合適的句子並添加些注釋,,原文地址如下:
http://blogs.msdn.com/b/webdev/archive/2009/01/29/t4-templates-a-quick-start-guide-for-asp-net-mvc-developers.aspx
在我們最近的部落格中提到的ASP.NET MVC Release Candidate中,我們使用了T4 (Text Template Transformation Toolkit)模板來實現了Add Controller和Add View的代碼自動產生功能。我們希望能使用T4給大家帶來開發速度上的提升,因為使用者可以在很大程度上定製這些模板。
模板的位置和重寫
Add Controller和Add View都是通過在後台執行T4模板來實現代碼自動產生的。通過一些工具可以修改模板來定製想要產生的程式碼。預設範本的位置在: [Visual Studio Install Directory]\Common7\IDE\ItemTemplates\[CSharp | VisualBasic]\Web\MVC\CodeTemplates\
你也可以把“CodeTemplates”目錄複寫到項目的根目錄以便作為每一個項目的基礎在上述位置重寫和定製模板(只需要建立目錄名為“CodeTemplates”的目錄,並在其下建立“AddController”和“AddView”的子目錄即可)。需要預設目錄下有一些模板的重寫可能不起作用,因為自動產生代碼時將會優先選取項目目錄中匹配的模板。還有一個重點需要注意,你可以為Add View功能增加自己的.tt 檔案,無論是在公用目錄下還是獨立的項目中,添加後都可以自動的顯示在Add View視窗的視圖選擇的下拉框中。
另外,複製上述檔案夾(添加.tt檔案)到項目中時,都會有警告提示,如:
(運行這些文本模板可能會對你的電腦產生危害。如果模板來源不可信請不要運行。)
點擊“Cancel”將不能使用T4模板(如果你複製“CodeTemplates”目錄並增加多個.tt檔案時,你都選擇了“Cancel”)。因為一旦項目發現一個.tt檔案,檔案的“自訂工具(CustomTool①)”屬性將被設定成“TextTemplatingFileGeneraror”,它會通知Visual Studio使用預設的T4宿主(Host②)去執行這個模板並且建立一個基於此模板內容的新的檔案(在模板所在的目錄)。
① :自訂工具是一個實現了 Visual Studio 定義的IVsSingleFileGenerator介面的特殊組件。T4 自訂工具由Microsoft.VisualStudio.TextTemplating.VSHost.TemplatedCodeGenerator類實現並且在註冊表中註冊在Visual Studio 下命名為TextTemplatingFileGenerator。Visual Studio 將使用該名稱尋找自訂工具、建立 COM 對象並調用其IVsSingleFileGenerator.Generate 方法
② :Microsoft.VisualStudio.TextTemplating.VSHost.10.0.dll 的TextTemplatingService服務實現Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost介面,為代碼產生引擎提供 Host (宿主)。在模板轉換過程中: Engine 負責代碼產生;Host負責提供轉換過程中行為具體實現及所需要的的所有外部資源,ITextTemplatingEngineHost和模板內容一起傳遞到Engine.ProcessTempalte方法中用於代碼產生
對於基於模板的一次性檔案產生或簡單的使用T4,產生器都可以作為好的的實現方式---但是,因為依賴於自訂模板的宿主的Add View 和Add Controller模板都包含代碼(後面會提到),使用預設的產生器執行模板將會建置錯誤。需要複製模板到項目中之後然後清空自訂工具屬性值。
注意:如果你想去掉複製.tt檔案時自動化佈建自訂工具的映射值,你可以通過註冊表實現---注意如果你想要恢複註冊表為預設值,你可以執行Visual Studio的恢複安裝,或手動改回。啟動登錄編輯程式並且找到指定的目錄(根據你的機器選擇是32位還是64位):
32位:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators
64位:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\9.0\Generators
展開“Generators”下第一層的每一個節點並找到“.tt”。設定“(Default)”項的值為空白,就可以了。
如果你想重寫通用範本,並且不想複製“CodeTemplates”目錄到你的項目(大概是你已經有了個同名目錄),你可以通過註冊表修改Add Controller 和Add View預設的目錄名。啟動登錄編輯程式並且找到指定的目錄(根據你的機器選擇是32位還是64位):
32-bit: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\MVC\CodeTemplates
64-bit: HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\9.0\MVC\CodeTemplates
改變“OverrideDir”項的值為你想要T4工具檢索的目錄名。需要注意的是,新設定的目錄下依然需要保證與原來相同的目錄結構,即包含“AddController”和“AddView”目錄。
編輯T4模板
如果你使用Visual Studio開啟一個.tt檔案,你可能會發現它的內容沒有層次---平鋪在上面。我們強烈推薦你使用T4編輯器,一個Clarius Consulting開發的Visual Studio外掛程式,它可以在你編輯模板時提供文法高亮和一些基本的T4語句的自動完成。有免費的“Community Edition”,以及更強大的“Professional Edition”---如果你有興趣可以比較下不同的特性。下面你將會看到,這個外掛程式真的讓模板製作有了很大不同。
深入剖析T4模板
最簡單的學習編輯自訂模板的方法是先看預設範本如何工作。為此,我們通過一些Add View的模板來瞭解“Create”(建立.tt檔案)。現在從頭開始:
這四行代碼都是指令。
1.第一行是模板指令,它的主要作用是通知T4引擎,模板使用哪種語言編寫。這裡所說的模板使用的語言並不是模板會輸出這種語言,而這種語言會控制模板的輸出(例如,模板中可能會報刊一個 if-else語句用來控制哪些文本被輸出)。在使用Add View 或者Add Controller之時,“HostSpecific”屬性需要設定為“True”,否則模板將不能訪問Add View 和Add Controller功能提供的資訊(比如將類型綁定為View的強型別,等等)。
2.緊接著的是輸出指令,它簡單的通過通知模板宿主來設定模板輸出檔案的副檔名---這不是MVC特有的工具,因為根據不同情況可能會忽略預設的副檔名(例如,如果我們依賴partial view ,副檔名應該是.ascx)。
3.接下來的兩行都是引用指令,C#中通常使用“using”,VB中使用“Imports”。如果你在模板中使用了用它們所寫的代碼,你需要在這個位置引用它們。
你可以在這裡找到更多T4指令的文檔:http://msdn.microsoft.com/en-us/library/bb126421.aspx
下面一點,注意一下後面的這行:
這行我們建立了一個變數“mvcHost”,將“Host”轉換類型並賦值給它。因為我們指令中設定了“HostSpecific”屬性為“True”,“Host”被自動提供給模板。MVC工具提供了一個自訂宿主,以便能將資訊傳遞給只有工具內部可訪問的模板。為了訪問我們的宿主類中提供的這些屬性,“Host”必須轉換為我們自訂的宿主類型“MvcTextTemplateHost”。
這個變數的使用實際上非常簡單:
首先需要注意的是,‘<#’ 和 ‘#>’標籤之間包含有一些的代碼。這兩個標籤用來調用語句塊和包含控制碼。你的模板可能要有條件的輸出文字區塊到輸出檔案中,同時保持其他文字區塊的正常輸出。上面,我們有一個if語句(使用C#,因為模板的語言使用模板指令設定成了C#),使用了“{”。這個if語句的“}”出現在後面一些行中的的第17行,在不同的語句塊中。注意,這裡的這個if語句訪問了宿主的“IsViewUserControl”屬性,這個屬性的作用是通知模板使用者選擇的是否是partial view。
模板中所有這些標記之外的文字區塊都會直接輸出到實際的檔案中。在上面的中,第14行的文本在標記塊之外,因此會直接輸出---儘管如此,它只會在12行的if語句值判斷為“true”的情況下才會輸出到檔案中。
你可以在這裡瞭解到更多關於T4語句塊的資訊:http://msdn.microsoft.com/en-us/library/bb126509.aspx
理解T4模板中控制碼的最簡單的方法是在大腦中將它串連為一個完整的程式。我們之前在第6行聲明的變數可以被之後的T4控制碼使用---之後每一個if-else分支條件都可以使用這個變數並且添加一些文本(灰色的)到輸出的檔案中。上面的If-else語句選擇一些由模板宿主提供的屬性傳遞給Add View模板。
後面一些行中有一個奇怪的語句塊:
我們聲明了一個“List<string>”類型的變數。我們怎麼能在T4代碼中使用List類型的?因為可以看到我們在模板頂部的引用指令:
第56行調用了一個方法“FilterProperties”---但是方法在哪?實際上這個方法的定義在模板底部:
如果你仔細看,這個語句塊有點不一樣,是以“<#+”開始的。這是一個用來表示類的塊,它們這樣工作:T4模板帶有所有的類的特徵,並且將這些特徵添加到在模板的背景編譯的類中。這不只限於方法,還包括屬性(通常包含在類中的)。像一個正規代碼檔案中的類成員一樣,它們可以被模板中的其他代碼訪問。
關於類特徵塊的更多資訊:http://msdn.microsoft.com/en-us/library/bb126541.aspx
我們的預設範本使用上面中的“FilterProperties”方法在預設輸出中的type包含的標記過濾獲得一些properties,這些標記必須是公用的和像GirdView一樣可以在設計器中顯示的。這與調用GridView .IsBindableType方法的結果在邏輯上是相同的。
(這段翻譯的很彆扭,所以附上原文,請大家幫忙指正)
Our default templates use the ‘FilterProperties’ method from the above screenshot to by default output markup only for some properties in the type – namely ones that are public and would also be displayed in the designer by things like GridView. This logic is identical to what you would get from calling the GridView.IsBindableType method.
在136行調用的“IsBindableType”是在模板後面一點位置被定義的:
如果你想改變我們模板過濾掉的某個屬性,你可以按照你的喜好修改任意一個方法。
最後,看看第65行:
這裡有一個新的標記開頭“<#=”。它被一個運算式塊調用並且用來插入T4代碼的值到輸出文本。像你在上面看到的,我們有一個foreach迴圈,迭代properties 並定義一個局部變數來迴圈調用“propertyName”。我們使用運算式區塊引述該變數,因為我們想為每一個屬性名稱輸出一個<th>標籤。
更多關於運算式塊:http://msdn.microsoft.com/en-us/library/bb126508.aspx
如你所見,上面各種使用T4模板的方法通過選擇性的輸出文本使T4成為一個強大的工具,協助我們獲得靈活的自訂的自動代碼產生。
MVC工具的T4宿主屬性
Add Controller 和Add View功能都通過模板宿主提供不同的屬性給模板,上述說明貫穿了建立模板的過程。這裡完整的列出了模板宿主的有效屬性,供你的模板使用(注意:這些屬性的實際名稱可能會因為不同的版本有所不同)。
Add Controller:
Property Name |
Type |
Description |
ItemName |
System.String |
帶有“Controller”尾碼的Controller類的名稱 |
NameSpace |
System.String |
產生的Controller類的命名空間 |
ExtraActionMethods |
System.Boolean |
指示使用者是否選擇在Add Controller視窗中擴充Action方法 |
ControllerRootName |
System.String |
不帶“Controller’”尾碼的Controller類的名稱 |
Add View:
Property Name |
Type |
Description |
ItemName |
System.String |
不帶副檔名的View名稱,例如顯示於Add View視窗中的 |
NameSpace |
System.String |
預設以View所在的目錄作為命名空間 |
IsViewUserControl |
System.Boolean |
在Add View視窗中使用者是否選擇了partial view |
IsViewContentPage |
System.Boolean |
使用者建立View時是否帶有master page |
IsViewPage |
System.Boolean |
使用者建立的是否是符合規範的視圖頁 |
MasterPage |
System.String |
使用者在視窗中選擇的master page路徑 (只能在 IsViewContentPage是true的時候使用) |
ContentPlaceholder |
System.String |
產生內容所在位置的預留位置名稱。是使用者輸入到Add View 視窗中內容預留位置ID |
ContentPlaceHolders |
System.Collections.Generic.List<System.String> |
master page中所有內容預留位置ID的列表, 如果View選擇了master page |
LanguageExtension |
System.String |
輸出檔案的副檔名 (包含”.”) |
ViewDataTypeGenericString |
System.String |
在View指令中用來輸出泛型”Inherits”屬性的字串(強型別 view). 例如: “<MyType>” 或 “(Of MyType)” |
ViewDataType |
System.Type |
被綁定的強型別View的Type對象。可以獲得類型的屬性資訊等 |
此外,你會發現一些提供給宿主的用用的屬性,比如正在執行的模板路徑。更多關於這些屬性: http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.texttemplating.itexttemplatingenginehost_properties.aspx
摘要
我們希望這篇文章帶給了你足夠關於T4模板的資訊,能幫你有效結合Visual Web Developer provides for ASP.NET MVC工具。你如果想知道這篇部落格之外更多的資訊,可以看看那的資訊(Scott Hanselman’s部落格不錯)並看看你能得到什麼。請回複您的評論,建議或問題。謝謝您的閱讀!
T4模板~又名基架---一種提升ASP.NET MVC開發速度的強大工具!