996
技術社區[雲棲]
解決T4模板的程序集引用的五種方案
在眾多.NET應用下的代碼生成方案中,比如CodeDOM,BuildProvider, 我覺得T4是最好的一種。關於T4的基本概念和模板結果,可以參考我的文章《基於T4的代碼生成方式》。如果要了解T4具體的應用,則可以參考我的文章《創建代碼生成器可以很簡單:如何通過T4模板生成代碼?》(上篇)(下篇)。如果你編寫T4模板,你不得不麵對一個問題——如何引用一個程序集?VS 2010采用了與VS2008不同的程序集引用的解析機製。本篇文章為你介紹在VS2010下5種不同的程序集引用的方式。
目錄
一、添加程序集引用解決不了問題
二、將引用程序集安裝到GAC
三、利用VS的PublicAssemblies目錄
四、指定程序集的具體路徑
五、采用環境變量
六、使用VS宏
如果你的T4模板需要調用一個自定義的類型,並且該類型定義在某個非係統程序集中,你就需要通過T4指令引用該程序集。在VS 2008環境下,你隻需要為,並且通過<@ assembly…#>指令的name屬性指定程序集(Dll)的文件名即可。比如,下麵的T4模板包含了對程序集Artech.T4AssemblyRefResovle.Foo.dll的引用。
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="Artech.T4AssemblyRefResovle.Foo.dll" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}
但是這種方式對於則行不通,因為T4引擎在解析和編譯模板的時候並不會從項目引用列表中去定位目標程序集。所以,對於上麵的T4模板,會出現如下的編譯錯誤。
其實我們有很多方式來解決這個問題,你首先想到的肯定是將引用的程序集安裝到GAC中。沒錯,這是一種解決方案,如果被引用的程序集具有強簽名的話。有一點需要注意的是,T4模板引用某個安裝於GAC的程序集的時候,在<#@ assembly…#>指令下。T4模板應該按照如下的方式定義。
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="Artech.T4AssemblyRefResovle.Foo" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}
為了讓T4引擎能夠找到引用的程序集,你可以將其拷貝到VS 2010的PublicAssemblies目的下,該目錄為。如果將Artech.T4AssemblyRefResovle.Foo.dll拷貝到該目錄下,你在T4模板的<#@ assembly…#>指令下就可以直接指定程序集名稱()或者程序集文件名()。
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="Artech.T4AssemblyRefResovle.Foo" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}
指定文件擴展名
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="Artech.T4AssemblyRefResovle.Foo.dll" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}
如果被引用的程序集被沒有被簽名,GAC的方式則不能使用,在這種情況下你需要指定程序集文件所在的位置,最直接的當然就是指定程序集文件的絕對路徑。在下麵的T4模板中,<#@ assembly…#>指令中指定的就是Artech.T4AssemblyRefResovle.Foo.dll文件的絕對路徑。
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="D:\T4AssemblyRefResovle\Lib\Artech.T4AssemblyRefResovle.Foo.dll" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}
采用程序集文件的絕對路徑這種硬編碼並不是一種推薦的解決方案,因為在團隊開發中,每個開發人員用於存放同一個程序集的地址可能不同,在這種情況下你可以采用環境變量的方式。你可以定義個環境變量(比如FooDir)表示本機用於保存程序集的目錄(比如D:\T4AssemblyRefResovle\Lib),那麼被引用的程序集就可以表示成:\Artech.T4AssemblyRefResovle.Foo.dll.
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="%FooDir%\Artech.T4AssemblyRefResovle.Foo.dll" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}
如果被引用的程序集所在目錄是在當前解決方案或者當前項目的子目錄(這是一種很常見的公共程序集保存方式),你還可以通過VS的宏命令來指定該目錄。比如我們的Artech.T4AssemblyRefResovle.Foo.dll保存在當前解決方案目錄的Lib子目錄下,該程序集的路徑就可以表示成:\Lib\Artech.T4AssemblyRefResovle.Foo.dll。
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="$(SolutionDir)\Lib\Artech.T4AssemblyRefResovle.Foo.dll" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}
注:上麵提到的程序集引用解決方案來源於《T4 Template error - Assembly Directive cannot locate referenced assembly in Visual Studio 2010 project.》
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
最後更新:2017-10-27 14:04:11