2011-11-24 110 views
0

我有一個T4模板,它引用另一個項目並對其輸出程序集進行一些反射以生成一些代碼。T4和MSBuild集成問題

在設計時使用Visual Studio 2010 SP1可以正常工作,因爲程序集在使用之前會被複制陰影。

但是,當我嘗試使用Visual Studio Modeling SDK中的MSBuild任務來執行構建時集成時,引用的程序集在第一次發生這種情況時被鎖定,並且之後我無法重建所引用的項目。

我假設這是因爲轉換引擎是MSBuild下完全不同的主機,並且不包括該Visual Studio主機執行的影子複製修復。

任何人都可以確認這是一個已知的問題,如果有任何解決方法?

回答

3

我意識到這是一個較舊的線程,但我想分享我的經驗,希望它可以幫助別人。

在VS 2012中,我們現在在設計器中支持影子副本。但是,在構建時轉換T4模板時(使用MSBuild或在Visual Studio中構建),我們仍然遇到上述的程序集鎖定問題。

爲了克服這個問題,我們將程序集加載到我們的T4 AppDomain中作爲字節數組。這使我們能夠反映裝配而不鎖定它。

<#@ template debug="false" hostspecific="true" language="C#" #> 
<#@ assembly name="System.Core" #> 
<#@ assembly name="System.Linq" #> 
<#@ assembly name="System.Runtime" #> 
<#@ import namespace="System.Reflection" #> 
<#@ import namespace="System.IO" #> 
<#@ import namespace="System.Linq" #> 
<#@ import namespace="System.Text" #> 
<#@ import namespace="System.Collections.Generic" #> 
<#@ output extension=".txt" #> 
<# 
    var assemblyPath = this.Host.ResolvePath(@"..\Path\To.dll"); 
    var assembly = LoadAssembly(assemblyPath); 
    foreach (Type t in assembly.GetTypes()) 
    { 
#> 
<#= t.FullName #> 
<# 
    } 
#> 
<#+ 
    public Assembly LoadAssembly(string path) 
    { 
     return Assembly.Load(File.ReadAllBytes(path)); 
    } 
#> 
+0

謝謝,這是一個有用的技巧。不幸的是,它不適用於我的具體情況,因爲我正在嘗試加載Silverlight DLL,並調用Assembly.Load()會導致我無法解決的問題。雖然會標記爲答案。 – Sam

+0

謝謝。我試圖在可行的情況下使用Portable Class Libraries。我可以想到兩個可以幫助你的選項。 1.將您想要模板的類移至PCL。 2.使用SL類實現的接口創建一個PCL。然後你會反映接口而不是SL類。 – RobV8R

0

爲了提高性能,T4引擎重用多個模板轉換,這導致所有引用 裝配文件被鎖定模板的AppDomain 。如果您在代碼生成過程中使用自己的程序集,則會出現問題,因爲程序集文件 只有在文件被T4解鎖後才能重新編譯。您可以強制 T4通過關閉並重新打開Visual Studio 解決方案或重新啓動Visual Studio本身來卸載該文件。或者, 考慮使用T4 Toolbox中的可用VolatileAssembly自定義僞指令,該僞指令可在裝入 之前創建該裝配的影子副本。

http://www.olegsych.com/2008/02/t4-assembly-directive/