我有一个.tt脚本,它需要引用几个外部程序集。
T4主机是否可以自动包含项目中引用的程序集,而不是我为每个程序集手动添加程序集指令?
例如,当使用相对于$(ProjecDir)
的路径时,从nuget引用程序集是一个移动目标。
使用像$(Project)binDebugExample.dll
这样的程序集路径似乎也不太理想,因为它要求以前的构建成功——如果您有一个在.cs文件中生成"ErrorGeneratingOutput
"的.tt文件,则可能不是这样!?
更新1:
因此,我对此进行了第二次尝试,但这一次我试图解决围绕"TransformOnBuild"的问题(顺便说一句,我可以强烈推荐@kzu的优秀项目:https://github.com/clariuslabs/TransformOnBuild)并且在不通过msbuild直接运行TextTransform时没有可用的$(SolutionDir)。不管怎样,我想出了一个两步解决方案。
-
msbuild目标使用WriteLinesToFile任务根据csproj文件中的引用生成一个.tt文件,该文件包含一个新的程序集指令列表。
-
项目中的任何其他.tt文件都可以包含自动生成的文件以注册项目程序集。
以下是目标的示例:
<Target Name="Write_AssemblyRefs_TT" BeforeTargets="TransformOnBuild">
<!-- A message for all to enjoy! -->
<WriteLinesToFile File="@(MyTextFile)"
Lines="<# /* AUTOGENERATED BY MSBUILD and Kern Herskind Nightingale */ #>"
Overwrite="true"
Encoding="Unicode" />
<!-- Output all assembly references with a HintPath -->
<WriteLinesToFile File="@(MyTextFile)"
Lines="<#@ assembly name="$(ProjectDir)%(Reference.HintPath)" #>"
Overwrite="false"
Encoding="Unicode"
Condition="'%(Reference.HintPath)' != ''" />
<!-- Output all project references - this could fail with custom nameing/build output dirs -->
<WriteLinesToFile File="@(MyTextFile)"
Lines="<#@ assembly name="$(ProjectDir)%(ProjectReference.RelativeDir)bin$(Configuration)%(ProjectReference.Name).dll" #>"
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
如果可以的话,我会在评论中发布这篇文章。
对于问题:不可能自动包含项目中引用的程序集,但可以限制您必须做的工作。
如果您在建议1中看到下面的链接,您可以在t4读取汇编代码之前使用c来定义它。这使得读取带有反射的目录并加载其中的每个程序集成为可能。所以问题是您的程序集将在哪里?
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 #>
这是未经测试的,但至少应该让你开始。供参考->如何从/bin目录中加载所有程序集
第二部分:
- 使用
$(SolutionDir)
,但这与$(Project)相同,只是低了一级。->如何在T4文本模板中使用自定义库/项目 - 使用c路径实用程序在运行时导航到所需的路径,但这可能需要首先编译程序集
- 在GAC中注册外部库。这样可以最大限度地解决您的问题,因为您根本不需要设置路径。请参阅->如何在GAC中注册.Net dll
编辑:这是一个工作动态包括。只需在任何其他.tt文件中引用由此生成的.tinclude的结果
我用调试器测试了它,它似乎可以工作。
并将组件本地化更改为您需要的位置。
<#@ 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:TEMP3mo0m0mq.dll" #>
<#@ assembly name="C:TEMP4ybsqre3.dll" #>
<#@ assembly name="C:TEMPao0bzedf.dll" #>
<#@ assembly name="C:TEMPbo2w102t.dll" #>
<#@ assembly name="C:TEMPc5o2syvv.dll" #>
<#@ assembly name="C:TEMPdz1fin10.dll" #>
<#@ assembly name="C:TEMPgiym0gef.dll" #>
<#@ assembly name="C:TEMPhjfgqkov.dll" #>
<#@ assembly name="C:TEMPibuz4wvb.dll" #>
<#@ assembly name="C:TEMPilrcwa2y.dll" #>
<#@ assembly name="C:TEMPk0yeumhb.dll" #>
<#@ assembly name="C:TEMPkirzdsqp.dll" #>
<#@ assembly name="C:TEMPksxl4f2z.dll" #>
<#@ assembly name="C:TEMPl4kja4ts.dll" #>
<#@ assembly name="C:TEMPljgxkpo0.dll" #>
<#@ assembly name="C:TEMPlkvkmlct.dll" #>
<#@ assembly name="C:TEMPlnofhhlq.dll" #>
<#@ assembly name="C:TEMPnbqhmjqd.dll" #>
<#@ assembly name="C:TEMPoc3pxhmq.dll" #>
<#@ assembly name="C:TEMPqb43ntcu.dll" #>
<#@ assembly name="C:TEMPqlyoyhyr.dll" #>
<#@ assembly name="C:TEMPsnwvtb00.dll" #>
<#@ assembly name="C:TEMPumhhb2wb.dll" #>
<#@ assembly name="C:TEMPxsyfel0b.dll" #>
<#@ assembly name="C:TEMPz1weyhko.dll" #>
你可以逃离<#带有\<#的字符看看这个。