我正在创建一个T4模板,我希望根据某些条件有条件地包含模板。例如,我尝试了以下内容......
<#switch(iocContainer) {#>
<#case "Autofac":#>
<#@ include file="Autofac\EntityTemplate.ttinclude" #>
<#@ include file="Autofac\ServiceTemplate.ttinclude" #>
<#@ include file="Autofac\RepositoryTemplate.ttinclude" #>
<#@ include file="Autofac\DbContextTemplate.ttinclude" #>
<#break;#>
<#case "Castle":#>
<#@ include file="Castle\EntityTemplate.ttinclude" #>
<#@ include file="Castle\ServiceTemplate.ttinclude" #>
<#@ include file="Castle\RepositoryTemplate.ttinclude" #>
<#@ include file="Castle\DbContextTemplate.ttinclude" #>
<#break;#>
<#case "nInject":#>
<#@ include file="nInject\EntityTemplate.ttinclude" #>
<#@ include file="nInject\ServiceTemplate.ttinclude" #>
<#@ include file="nInject\RepositoryTemplate.ttinclude" #>
<#@ include file="nInject\DbContextTemplate.ttinclude" #>
<#break;
}#>
问题是当模板引擎运行时,它似乎在评估任何代码之前预处理所有包含。因此上面的switch语句没有运行,T4试图包含所有文件。
有没有办法有条件地包含T4模板?
答案 0 :(得分:1)
不,T4不包括设计的条件包含。这些指令都将被处理。
如果颠倒逻辑,你可以解决这个问题。将switch语句上方和下方的T4内容拆分为两个单独的文件(让我们称之为start.ttinclude
和end.ttinclude
)。然后创建三个单独的T4模板,例如autofac.tt
,castle.tt
和ninject.tt
。每个都看起来像这样(这是castle.tt
):
<#@ include file="start.ttinclude" #>
<#@ include file="Castle\EntityTemplate.ttinclude" #>
<#@ include file="Castle\EntityTemplate.ttinclude" #>
<#@ include file="Castle\EntityTemplate.ttinclude" #>
<#@ include file="Castle\EntityTemplate.ttinclude" #>
<#@ include file="end.ttinclude" #>
答案 1 :(得分:1)
或者,将模板的内容放在#IF #ENDIF块中,并使用#DEFINEs导致内容被跳过,即使包含文件本身也是如此。
答案 2 :(得分:0)
如果您不介意在Visual Studio容器中运行,那么DTE可以帮助您。
<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="EnvDTE" #>
<#@ Assembly Name="System.Core" #>
<#@ Assembly Name="System.Data" #>
<#@ Assembly Name="System.Xml" #>
<#@ Assembly Name="System.Xml.Linq" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System" #>
<#@ Import namespace="System.Linq" #>
<#@ Import namespace="System.Reflection" #>
<#@ Import namespace="System.Linq.Expressions" #>
<#@ Import namespace="System.Collections.Generic" #>
<#@ Import namespace="System.Linq" #>
<#@ Import namespace="System.Text" #>
<#
if(isDefined("spike2" , "TTs")) {
WriteLine("//the constant TTs is defined");
}
else
{
WriteLine("//the constant TTs is not defined");
}
#>
<#+
private bool isDefined(string projectName, string constantToCheck){
IServiceProvider serviceProvider = (IServiceProvider)this.Host;
DTE dte = serviceProvider.GetService(typeof(DTE)) as DTE;
try
{
// find a project called "Spike2"
Project prj = (from p in getProjects(dte) where p.Name.ToLower() == projectName.ToLower() select p).FirstOrDefault();
// get its active configuration
var config = prj.ConfigurationManager.ActiveConfiguration;
var defineConstants = (from p in getConfigProperties(config) where p.Name == "DefineConstants" select p.Value).FirstOrDefault().ToString();
var constants = defineConstants.Split(';');
return Array.Exists(constants, define => define == constantToCheck);
}
catch(Exception ex)
{
Write(ex.Message);
}
return false;
}
static private IEnumerable<Property> getConfigProperties(Configuration config) {
for(int i=1; i <= config.Properties.Count; i++)
{
yield return config.Properties.Item(i);
}
}
static private IEnumerable<Project> getProjects(DTE dte) {
for(int i=1; i <= dte.Solution.Projects.Count; i++)
{
yield return dte.Solution.Projects.Item(i);
}
}
#>
答案 3 :(得分:0)
我想为每台开发者机器添加一个不同的配置文件,并且还要有一个默认的app.config。这仅在您不想处理“包含”文件时才有效。
文件名App.tt。
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".config" #>
<#
string pathToConfigurations = Host.ResolvePath("Configurations");
string pathToMachine = Path.Combine(pathToConfigurations, Environment.MachineName + ".config");
if (File.Exists(pathToMachine))
{
Write(File.ReadAllText(pathToMachine));
}
else
{
Write(File.ReadAllText(Path.Combine(pathToConfigurations, "App.config")));
}
#>