T4 text template unable to call other code

Viewed 109

Open VisualStudio2022 and create a new net6.0 class library.

Create a class to use in the T4 template and create a T4 template and use the class.

Class:

namespace ClassLibraryT4
{
    public class Class1
    {
        public static string DoTheThing() { return "TheThing"; }
    }
}

Now build the project so that its dll file exists on disc.

T4:

<#@ template debug="false" hostspecific="false" language="C#" #>

<#@ assembly name="$(SolutionDir)ClassLibraryT4\bin\Debug\net6.0\ClassLibraryT4.dll" #>
<#@ import namespace="ClassLibraryT4" #>

<#@ output extension=".cs" #>

namespace ClassLibraryT4 
{
    public class TheGeneratedClass
    {
        private const string _TheThing = "<# Class1.DoTheThing(); #>";
    }
}

The T4 now fails to run because

nThe type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

If I add to the T4:

<#@ assembly name="System.Runtime"#>

Then I now get

Error       Running transformation: System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
File name: 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
   at Microsoft.VisualStudio.TextTemplating6765B00A4659E4D1054752E9A2C829A21EECD20197C4EDDD8F5675E0DB91730A0DFF4528F1622E70821097EC90F6A2D0DE05F4739B3E0CD1BCAF45AAA20D419D.GeneratedTextTransformation.TransformText()
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
   at Microsoft.VisualStudio.TextTemplating.TransformationRunner.PerformTransformation()

Can T4s work?

It seems to be impossible to use any outisde code; this does work in the T4:

private const string _TheThing = "<#= 5+2 #>";

and so does this:

private const string _TheThing = "<#= Thing() #>";
...
<#+ 
private static string Thing() {
    return "thing";
    }
#>

but this also has the _Could not load file or assembly System.Runtime...` problem:

<#+ 
private static string Thing() {
    return Class1o.DoTheThing();
    }
#>
2 Answers

Can T4s work? Yes. You just need to ensure that all used dll's are for x86 architecture. This is limitation by Visual Studio as it is a 32-bit app.

The safest way to get this working is to use netstandard2.0 for any assembly to be loaded in a T4 template. If you include plain C# code (via include directive) only, then you may get away with it even if it uses net6.0 APIs after tweaking the assembly directives for a while. However, you will need to tweak it up to the point where it works for both, the Visual Studio and the MSBuild hosts.

Related