在T4中将项目引用用作组装路径 [英] Using project references as assembly paths in T4
问题描述
我有一个.tt脚本,该脚本需要引用几个外部程序集.
I have a .tt script that needs to reference a couple of external assemblies.
T4主机是否可以自动包含项目中引用的程序集-而不是我手动为每个程序集添加一个程序集指令?
Is it possible for the T4 host to automatically include the assemblies referenced in the project - rather than me manually adding an assembly directive for each one?
例如当使用相对于 $(ProjecDir)
的路径时,从nuget引用程序集是一个移动目标.
E.g. Referencing an assembly from a nuget is a moving target when using a path relative to $(ProjecDir)
.
使用像 $(Project)\ bin \ Debug \ Example.dll
这样的程序集路径似乎也不是最优的-因为它要求构建以前已经成功完成-如果您有一个.tt文件在.cs文件中生成" ErrorGeneratingOutput
"!?
Using assembly paths like $(Project)\bin\Debug\Example.dll
also seems less than optimal - as it requires the build to have been successful previously - which is probably not the case if you have a .tt file generating the "ErrorGeneratingOutput
" in a .cs file!?
更新1:
因此,我此时有了第二次尝试,但是这次尝试解决"TransformOnBuild"周围的问题(作为一个侧面说明,我强烈推荐@kzu的出色项目:
So I have had a second stab at this but this time trying to tackle the issue around "TransformOnBuild" ( as a side note I can highly recommend @kzu's excellent project: https://github.com/clariuslabs/TransformOnBuild) and not having $(SolutionDir) available when not running TextTransform via direct from msbuild. Anyway - I came up with a 2-step solution.
-
msbuild目标使用WriteLinesToFile任务生成一个.tt文件,其中包含基于csproj文件中的引用的汇编指令的最新列表.
msbuild target uses WriteLinesToFile task to generates a .tt file with a fresh list of assembly directives based on the references found in the csproj file.
项目中的任何其他.tt文件都可以包括自动生成的文件,以注册项目程序集.
Any other .tt files in the project can the include the auto-generated file to get project assemblies registered.
以下是目标的示例:
<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文件中(简单):
And how to include it in the T4 file (trivial):
<#@ include file="AssemblyRefs.tt" #>
代码生成器的代码生成:)
Code generation for the code generator :)
更新2:
我创建了一个Nuget包,以轻松添加上述程序集指令生成构建目标:
I have created a Nuget package to make it easy to add the above assembly directive generation build target: https://www.nuget.org/packages/AssemblyReferencesTT/1.0.12
推荐答案
如果可以的话,我会对此发表评论.
i would have posted this in comment if i could.
问题:不可能自动包含项目中引用的程序集,但是您可以限制必须做的工作.
for the question: it is not possible to include the assemblies referenced in the project automatically, but you can limit the work you have to do.
如果您在建议编号1的下面看到链接,则可以使用c#定义汇编代码,然后再由t4读取它.这样就可以读取带有反射的目录并在其中加载每个程序集.所以问题是您的程序集在哪里?
if you see below link in suggestion number 1, you can use c# to define assembly code before it is read by the t4. which make it possible to read a directory with reflection and load each assembly there.so the question is where will your assembly be ?
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目录
this is untested but should get you started at lest. for reference -> how to load all assemblies from within your /bin directory
第二部分:
- 使用
$(SolutionDir)
,但这与$(Project)相同,除了低一级.-> 如何使用自定义库/项目在T4文字模板中? - 在运行时使用c#路径实用程序导航到所需的路径,但这又可能需要程序集先进行编译.
- 在GAC中注册外部库.因为您根本不需要设置路径,所以这可以最大程度地解决您的问题.参见-> 如何在GAC中注册.Net dll?
- using
$(SolutionDir)
but this is the same as the $(Project) one except one level lower. -> How do I use custom library/project in T4 text template? - use c# path utilities to navigate to the wanted path at runtime, but again this might require the assembly to compile first.
- Registering the External Library in GAC. this seams to resolve your problem the most since you will not have to set a path at all. see -> How to register a .Net dll in GAC?
这是一个有效的动态包含.只需在其他任何.tt文件中引用此文件生成的.ttinclude的结果
here is a working dynamic include. just reference the result of the .ttinclude generated by this in any other .tt file
我用调试器对其进行了测试,它似乎可以正常工作.
i tested it with the debugger and it seems to work.
并更改程序集本地化以指向您需要的位置.
and change assembly localisation to point where you need it to.
<#@ 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" #>
您可以使用\<#转义<#字符,请参见此.
you can escape the <# character with \<# see this.
这篇关于在T4中将项目引用用作组装路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!