Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在T4中将项目引用用作程序集路径_C#_.net_.net Assembly_T4_Auto Generate - Fatal编程技术网

C# 在T4中将项目引用用作程序集路径

C# 在T4中将项目引用用作程序集路径,c#,.net,.net-assembly,t4,auto-generate,C#,.net,.net Assembly,T4,Auto Generate,我有一个.tt脚本,需要引用几个外部程序集 T4主机是否可以自动包含项目中引用的程序集,而不是手动为每个程序集添加一个程序集指令 例如,当使用相对于$(ProjecDir)的路径时,从nuget引用程序集是一个移动目标 使用像$(Project)\bin\Debug\Example.dll这样的程序集路径似乎也不是最理想的-因为它要求构建之前已经成功-如果在.cs文件中有一个.tt文件生成“ErrorGeneratingOutput”,则可能不是这样 更新1: 因此,我在这方面进行了第二次尝试,

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

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

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

使用像
$(Project)\bin\Debug\Example.dll这样的程序集路径似乎也不是最理想的-因为它要求构建之前已经成功-如果在.cs文件中有一个.tt文件生成“
ErrorGeneratingOutput
”,则可能不是这样

更新1:

因此,我在这方面进行了第二次尝试,但这次尝试解决“TransformOnBuild”(作为补充说明,我可以强烈推荐@kzu的优秀项目:)以及在不通过直接从msbuild运行TextTransform时没有可用的$(SolutionDir)。无论如何,我想出了一个两步解决方案

  • msbuild目标使用WriteListFile任务生成一个.tt文件,其中包含基于csproj文件中找到的引用的程序集指令的新列表

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

  • 以下是目标的一个示例:

    <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文件中(琐碎):

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

    更新2:


    我已经创建了一个Nuget包,以便于添加上面的汇编指令生成构建目标:

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

    关于问题: 无法在项目中自动包含引用的程序集,但可以限制必须执行的工作

    如果您在建议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 #>
    
    输出:

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

    如果这里描述的$(libDir)技术可能是解决方案的一部分,您就不会感到奇怪了:herskinduk,我找不到一种方法来做这件事,但是是否可以生成另一个具有正确路径的tt文件,然后生成这个生成的tt文件?@samy我认为这是可能的。基本上,这源于需要通过nuget分发一个.tt文件。如果我可以使用Nuget来管理依赖项,那将是一件非常巧妙的事情——不过这需要T4能够加载项目引用。也许MEF就是答案?以下是我到目前为止得到的答案(见第105行)。我仍然有两个难看的汇编指令,但其余的程序集是动态加载的,并通过MEF注入的。我一直在考虑创建一个自定义主机来促进这一点。好主意/坏主意?我认为这不是正确答案。查找项目引用路径可以这样做:但是不能按照您建议的方式动态输出。这是一个大问题。关于你的三点:1+2)请参阅我之前的评论,以了解定位项目引用的有效方法。查找程序集不是问题所在。让T4主机将它们添加为程序集引用才是真正的杀手。3) 将程序集添加到GAC可能有一些相似之处,但我不认为它构成了最初描述的问题的解决方案。@herskinduk是的,GAC方法是有问题的,因为您需要记住在将要构建的每台机器上执行此操作。我提出了一个工作模型,也许有办法让它直接工作,我仍在努力解决这个问题。看看你的编辑-记住,问题是它没有输出字符串“”。。。问题是让T4主机加载程序集,以便您可以在T4代码中使用它们。@herskinduk然后“#>\
    <#@ 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" #>