在T4中将项目引用用作组装路径 [英] Using project references as assembly paths in T4

查看:43
本文介绍了在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.

  1. msbuild目标使用WriteLinesToFile任务生成一个.tt文件,其中包含基于csproj文件中的引用的汇编指令的最新列表.

  1. 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="&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文件中(简单):

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

第二部分:

  1. 使用 $(SolutionDir),但这与$(Project)相同,除了低一级.-> 如何使用自定义库/项目在T4文字模板中?
  2. 在运行时使用c#路径实用程序导航到所需的路径,但这又可能需要程序集先进行编译.
  3. 在GAC中注册外部库.因为您根本不需要设置路径,所以这可以最大程度地解决您的问题.参见-> 如何在GAC中注册.Net dll?
  1. 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?
  2. use c# path utilities to navigate to the wanted path at runtime, but again this might require the assembly to compile first.
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆