Подтвердить что ты не робот

Использование ссылок проекта в качестве путей сборки в T4

У меня есть .tt script, который должен ссылаться на пару внешних сборок.

Возможно ли, чтобы хост T4 автоматически включал сборки, указанные в проекте, вместо того, чтобы вручную добавлять директиву сборки для каждого из них?

например. Ссылка на сборку из nuget является движущейся мишенью при использовании пути относительно $(ProjecDir).

Использование путей сборки, таких как $(Project)\bin\Debug\Example.dll, также кажется менее оптимальным - поскольку это требует, чтобы сборка была успешной ранее - это, вероятно, не так, если у вас есть файл .tt, генерирующий "ErrorGeneratingOutput" в a. cs file!?

Обновление 1:

Итак, у меня был второй удар, но на этот раз, пытаясь решить проблему вокруг "TransformOnBuild" (в качестве побочной заметки я могу очень рекомендовать @kzu отличный проект: https://github.com/clariuslabs/TransformOnBuild) и не имея $(SolutionDir), доступного, если не запущен TextTransform через direct from msbuild. Во всяком случае - я придумал двухэтапное решение.

  • Цель msbuild использует задачу WriteLinesToFile для создания файла .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 (тривиальный):

<#@ include file="AssemblyRefs.tt" #>

Генерация кода для генератора кода:)

Обновление 2:

Я создал пакет Nuget, чтобы упростить добавление указанной выше сборки сборки сборки сборки: https://www.nuget.org/packages/AssemblyReferencesTT/1.0.12

4b9b3361

Ответ 1

Я бы разместил это в комментарии, если бы мог.

для вопроса: невозможно включить сборки, указанные в проекте, автоматически, но вы можете ограничить работу, которую вы должны выполнить.

если вы видите ссылку ниже в предложении номер 1, вы можете использовать С# для определения кода сборки, прежде чем он будет прочитан t4. которые позволяют читать директорию с отражением и загружать каждую сборку там. Вопрос в том, где будет ваша сборка?

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

для второй части:

Изменить: здесь включена рабочая динамика. просто ссылайтесь на результат .ttinclude, сгенерированный этим в любом другом файле .tt

Я тестировал его с помощью отладчика и, похоже, работал.

и измените локализацию сборки, чтобы указать, где она вам нужна.

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

вы можете избежать символа < # с \< # see this.