2014-09-23 50 views
13

我有一個需要引用幾個外部程序集的.tt腳本。在T4中使用項目引用作爲程序集路徑

T4主機是否可以自動包含項目中引用的程序集 - 而不是手動爲每個程序集添加一個程序集指令?

E.g.當使用相對於$(ProjecDir)的路徑時,從nuget引用裝配體是移動目標。

使用像$(Project)\bin\Debug\Example.dll這樣的程序集路徑似乎也不是最佳 - 因爲它需要以前的構建已經成功 - 如果在.cs文件中生成「ErrorGeneratingOutput」的.tt文件,則可能不是這種情況! ?

更新1:

所以我有第二刺在這一點,但這個時間,試圖圍繞解決這個問題「TransformOnBuild」(作爲一個側面說明,我可以強烈推薦@ kzu的優秀項目:https://github.com/clariuslabs/TransformOnBuild)而沒有通過直接從msbuild運行TextTransform時沒有$(SolutionDir)可用。無論如何 - 我想出了一個2步驟的解決方案。

  1. 的MSBuild目標使用WriteLinesToFile任務生成基於在的csproj文件中找到的引用裝配指令的新鮮列表.TT文件。

  2. 項目中的任何其他.tt文件都可以包含自動生成的文件以獲取項目程序集註冊。

這裏是目標的一個示例:

<Target Name="Write_AssemblyRefs_TT" BeforeTargets="TransformOnBuild"> 
    <!-- A message for all to enjoy! --> 
    <WriteLinesToFile File="@(MyTextFile)" 
    Lines="&lt;# /* AUTOGENERATED BY MSBUILD and Kern Herskind Nightingale */ #&gt;" 
    Overwrite="true" 
    Encoding="Unicode" /> 
    <!-- Output all assembly references with a HintPath --> 
    <WriteLinesToFile File="@(MyTextFile)" 
    Lines="&lt;#@ assembly name=&quot;$(ProjectDir)%(Reference.HintPath)&quot; #&gt;" 
    Overwrite="false" 
    Encoding="Unicode" 
    Condition="'%(Reference.HintPath)' != ''" /> 
    <!-- Output all project references - this could fail with custom nameing/build output dirs --> 
    <WriteLinesToFile File="@(MyTextFile)" 
    Lines="&lt;#@ assembly name=&quot;$(ProjectDir)%(ProjectReference.RelativeDir)bin\$(Configuration)\%(ProjectReference.Name).dll&quot; #&gt;" 
    Overwrite="false" 
    Encoding="Unicode" /> 
</Target> 
<ItemGroup> 
    <MyTextFile Include="AssemblyRefs.tt" /> 
</ItemGroup> 

而如何將其包含在T4文件(簡單):

<#@ include file="AssemblyRefs.tt" #> 

代碼生成的代碼發生器:)

更新2:

我創建了一個NuGet包,使其方便地添加上述集指令生成構建目標:https://www.nuget.org/packages/AssemblyReferencesTT/1.0.12

+0

想知道這裏所描述的$(LIBDIR)技術可能是解決方案的一部分:HTTP ://blogs.msdn.com/b/t4/archive/2013/08/29/what-s-new-in-t4-for-visual-studio-2013.aspx – herskinduk 2014-10-06 08:45:23

+0

herskinduk,我找不到方法要做到這一點,但是不可能用正確的路徑生成另一個tt文件,然後構建th是生成tt文件? – samy 2014-10-07 14:36:14

+0

@samy我會認爲這是可能的。基本上,這源於需要通過nuget發佈.tt文件。如果我可以使用Nuget來管理依賴關係,這將會是超級光滑 - 這需要T4能夠加載項目引用。也許MEF是答案? – herskinduk 2014-10-07 21:21:03

回答

3

我會評論,如果我可以公佈這。

問題: 不可能自動包含項目中引用的程序集,但是您可以限制您必須執行的工作。

如果您在建議編號1中看到以下鏈接,則可以使用c#在t4讀取它之前定義彙編代碼。這使得可以用反射讀取一個目錄,並在那裏加載每個程序集。所以問題是你的程序集將會在哪裏?

List<Assembly> allAssemblies = new List<Assembly>(); 
string path = Assembly.GetExecutingAssembly().Location; 

foreach (string dll in Directory.GetFiles(path, "*.dll")) 
    allAssemblies.Add(Assembly.LoadFile(dll)); 
    <#@ assembly name=dll #> 

這是未經測試,但應該讓你開始在最短的時間。 供參考 - >how to load all assemblies from within your /bin directory

用於第二部分:

  1. 使用$(SolutionDir)但這是一樣的$(項目)一個除了一個電平低。 - >How do I use custom library/project in T4 text template?
  2. 使用c#路徑實用程序在運行時導航到想要的路徑,但這又可能需要程序集先編譯。
  3. 在GAC中註冊外部庫。這接近於解決你的問題,因爲你根本不需要設置路徑。看到 - >How to register a .Net dll in GAC?

編輯:這裏是一個工作的動態包括。只需參考.ttinclude在其他任何.tt文件中產生的結果

我用調試器測試過它,它似乎工作。

並將裝配本地化更改爲您需要的位置。

<#@ template debug="false" hostspecific="false" language="C#" #> 
<#@ assembly name="System.Core" #> 
<#@ assembly name="System.Net.Http" #> 
<#@ import namespace="System.Linq" #> 
<#@ import namespace="System.Text" #> 
<#@ import namespace="System.Collections.Generic" #> 
<#@ import namespace="System.Reflection" #> 
<#@ import namespace="System.IO" #> 
<#@ output extension=".ttinclude" #><# 

List<Assembly> allAssemblies = new List<Assembly>(); 
string file = Assembly.GetExecutingAssembly().Location; 
if(file!= "") 
{ 
    string path = Path.GetDirectoryName(file).TrimEnd(); 
    if(path != "") 
     foreach (string dll in Directory.GetFiles(path, "*.dll")) 
     { 
      if(dll != "") 
      { 
       allAssemblies.Add(Assembly.LoadFile(dll)); 
       #>\<#<#= "@ assembly name=\""+ dll +"\" "#>\#><#="\n"#><# 
      } 
     } 
} 

#> 

輸出:

<#@ assembly name="C:\TEMP\3mo0m0mq.dll" #> 
<#@ assembly name="C:\TEMP\4ybsqre3.dll" #> 
<#@ assembly name="C:\TEMP\ao0bzedf.dll" #> 
<#@ assembly name="C:\TEMP\bo2w102t.dll" #> 
<#@ assembly name="C:\TEMP\c5o2syvv.dll" #> 
<#@ assembly name="C:\TEMP\dz1fin10.dll" #> 
<#@ assembly name="C:\TEMP\giym0gef.dll" #> 
<#@ assembly name="C:\TEMP\hjfgqkov.dll" #> 
<#@ assembly name="C:\TEMP\ibuz4wvb.dll" #> 
<#@ assembly name="C:\TEMP\ilrcwa2y.dll" #> 
<#@ assembly name="C:\TEMP\k0yeumhb.dll" #> 
<#@ assembly name="C:\TEMP\kirzdsqp.dll" #> 
<#@ assembly name="C:\TEMP\ksxl4f2z.dll" #> 
<#@ assembly name="C:\TEMP\l4kja4ts.dll" #> 
<#@ assembly name="C:\TEMP\ljgxkpo0.dll" #> 
<#@ assembly name="C:\TEMP\lkvkmlct.dll" #> 
<#@ assembly name="C:\TEMP\lnofhhlq.dll" #> 
<#@ assembly name="C:\TEMP\nbqhmjqd.dll" #> 
<#@ assembly name="C:\TEMP\oc3pxhmq.dll" #> 
<#@ assembly name="C:\TEMP\qb43ntcu.dll" #> 
<#@ assembly name="C:\TEMP\qlyoyhyr.dll" #> 
<#@ assembly name="C:\TEMP\snwvtb00.dll" #> 
<#@ assembly name="C:\TEMP\umhhb2wb.dll" #> 
<#@ assembly name="C:\TEMP\xsyfel0b.dll" #> 
<#@ assembly name="C:\TEMP\z1weyhko.dll" #> 

你可以用\ <#逃脫<#字符看到 this.

+0

我不認爲這是正確的答案。查找項目參考路徑可以這樣完成:https://gist.github.com/herskinduk/4528231150d13439e325 但是<#@ assembly#>無法按照您的建議動態輸出。這是一個大問題。 – herskinduk 2014-10-07 14:00:09

+0

關於你的三點:1 + 2)請參閱我以前的評論,以找到找到項目參考的有效方法。尋找組件不是問題。 T4主機將它們作爲組件參考添加是真正的殺手。 3)將程序集添加到GAC可能有一些問題,但我認爲它不構成對最初描述的問題的解決方案。 – herskinduk 2014-10-07 14:11:00

+0

@herskinduk是的GAC方式是有問題的,因爲您需要記住在每臺將構建的機器上執行此操作。我想出了一個工作模式,可能有一種方法可以使它直接工作,我仍然試圖找出這個問題。在您的編輯 – Rugdr 2014-10-07 15:40:00

相關問題