在T4中使用项目引用作为程序集路径

时间:2014-09-23 08:14:24

标签: c# .net .net-assembly t4 auto-generate

我有一个.tt脚本需要引用几个外部程序集。

T4主机是否可以自动包含项目中引用的程序集 - 而不是手动为每个程序集添加程序集指令?

E.g。当使用相对于$(ProjecDir)的路径时,从nuget引用程序集是一个移动目标。

使用像$(Project)\bin\Debug\Example.dll这样的汇编路径似乎也不是最优的 - 因为它要求构建先前已经成功 - 如果你有一个.tt文件生成" {{ 1}}"在.cs文件中!?

更新1:

所以我对此进行了第二次尝试,但这一次试图解决围绕" TransformOnBuild" (作为旁注,我强烈推荐@ kzu的优秀项目:https://github.com/clariuslabs/TransformOnBuild),并且在没有通过msbuild直接运行TextTransform时没有$(SolutionDir)。无论如何 - 我想出了一个两步解决方案。

  1. msbuild target使用WriteLinesToFile任务根据csproj文件中的引用生成一个带有新的程序集指令列表的.tt文件。

  2. 项目中的任何其他.tt文件都可以包含自动生成的文件以获取已注册的项目程序集。

  3. 以下是目标的示例:

    ErrorGeneratingOutput

    如何将其包含在T4文件中(琐碎):

    <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>
    

    代码生成器的代码生成:)

    更新2:

    我创建了一个Nuget包,可以轻松添加上面的汇编指令生成构建目标:https://www.nuget.org/packages/AssemblyReferencesTT/1.0.12

1 个答案:

答案 0 :(得分:3)

如果可以的话,我会在评论中发布这个。

问题: 不能自动包含项目中引用的程序集,但您可以限制您必须完成的工作。

如果您在建议编号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 #>

这是未经测试但应该让你开始,以免。 供参考 - &gt; how to load all assemblies from within your /bin directory

第二部分:

  1. 使用$(SolutionDir)但这与$(Project)相同,只是低一级。 - &GT; How do I use custom library/project in T4 text template?
  2. 使用c#path实用程序在运行时导航到所需路径,但这可能需要先组装程序集。
  3. 在GAC中注册外部库。这种接缝最能解决您的问题,因为您根本不需要设置路径。看 - &gt; How to register a .Net dll in GAC?
  4. 编辑:这是一个有效的动态包含。只需在任何其他.tt文件中引用由此生成的.ttinclude的结果

    我用调试器测试它似乎工作。

    并将程序集本地化更改为您需要的位置。

    <#@ 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" #> 
    

    您可以使用\&#;# this.

    转义&lt;#字符