2011-11-24 73 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/