Multi-level nested multi-projects template is available! (tested on Visual Studio 2019)
Parent template parameters available in nested projects with prefix 'ext_' when you declare <ProjectTemplateLink ... CopyParameters="true">
.
See Reserved template parameters - Parameter - ext_* in
Docs - Visual Studio - IDE - Develop - Solutions and projects - Customize templates - Template parameters
Result parameters values from my test:
$safeitemname$ = "Class1"
$safeprojectname$ = "SubProject1"
$ext_safeprojectname$ = "Nested"
$ext_ext_safeprojectname$ = "SolutionName"
Test description
Template file structure (in zip-archive MyTemplate.zip
):
.\TopSolution.vstemplate
.\Nested\Nested.csproj
.\Nested\SupportTemplate.vstemplate
.\Nested\SubProject1\SubProject1.vstemplate
.\Nested\SubProject1\SubProject1.csproj
.\Nested\SubProject1\Class1.cs
.\Nested\SubProject2\SubProject2.vstemplate
.\Nested\SubProject2\SubProject2.csproj
.\Nested\SubProject2\Class2.cs
MyTemplate.zip:\TopSolution.vstemplate
content
...
<TemplateContent>
<ProjectCollection>
<ProjectTemplateLink ProjectName="Nested" CopyParameters="true">Nested\SupportTemplate.vstemplate</ProjectTemplateLink>
</ProjectCollection>
</TemplateContent>
...
MyTemplate.zip:\Nested\Nested.csproj
content (hasn't any refs or items):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
</Project>
MyTemplate.zip:\Nested\SupportTemplate.vstemplate
content:
...
<TemplateContent>
<ProjectCollection>
<ProjectTemplateLink ProjectName="SubProject1" CopyParameters="true">SubProject1\SubProject1.vstemplate</ProjectTemplateLink>
<ProjectTemplateLink ProjectName="SubProject2" CopyParameters="true">SubProject2\SubProject2.vstemplate</ProjectTemplateLink>
</ProjectCollection>
</TemplateContent>
...
MyTemplate.zip:\Nested\SubProject1\SubProject1.vstemplate
content:
...
<TemplateContent>
<Project TargetFileName="SubProject1.csproj" File="SubProject1.csproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true" TargetFileName="Class1.cs">Class1.cs</ProjectItem>
</Project>
</TemplateContent>
...
MyTemplate.zip:\Nested\SubProject2\SubProject2.vstemplate
content:
...
<TemplateContent>
<Project TargetFileName="SubProject2.csproj" File="SubProject2.csproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true" TargetFileName="Class2.cs">Class2.cs</ProjectItem>
</Project>
</TemplateContent>
...
Files structure created from template MyTemplate with project name 'SolutionName':
SolutionName\SolutionName.sln
SolutionName\Nested\Nested.csproj
SolutionName\Nested\SubProject1\SubProject1.csproj
SolutionName\Nested\SubProject1\Class1.cs
SolutionName\Nested\SubProject2\SubProject2.csproj
SolutionName\Nested\SubProject2\Class2.cs
MyTemplate.zip:\Nested\SubProject1\Class1.cs
content (in template archive):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace $safeprojectname$
{
public class Class1
{
static void Main(string[] args)
{
Console.WriteLine("$safeitemname$"); // = safeitemname
Console.WriteLine("$safeprojectname$"); // = safeprojectname
Console.WriteLine("$ext_safeprojectname$"); // = ext_safeprojectname
Console.WriteLine("$ext_ext_safeprojectname$"); // = ext_ext_safeprojectname
}
}
}
SolutionName\Nested\SubProject1\Class1.cs
content (after top project with 'SolutionName' created from template):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace $safeprojectname$
{
public class Class1
{
static void Main(string[] args)
{
Console.WriteLine("Class1"); // = safeitemname
Console.WriteLine("SubProject1"); // = safeprojectname
Console.WriteLine("Nested"); // = ext_safeprojectname
Console.WriteLine("SolutionName"); // = ext_ext_safeprojectname
}
}
}