将 T4 生成的文件包含在与模板文件相同的文件夹中
Include T4 generated files on the same folder of the template file
我正在尝试将保存的文件添加到我的 T4 模板文件的当前项目中。
SaveOutput
方法按预期保存了文件,但是当我使用 IncludeInCurrentProject
方法时,调用了 ProjectItems.AddFromFile
(docs here),然后文件被添加到项目的 root。
我想将 SaveOutput
方法生成的文件包含在项目的确切位置。
这是我现在拥有的:
这是我的 .tt 文件:
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".sql" #>
<#@ assembly name="Microsoft.VisualBasic.dll" #>
<#@ assembly name="EnvDTE" #>
<#@ import Namespace="System.IO" #>
<#@ import namespace="EnvDTE" #>
<#
var MigrationName = Microsoft.VisualBasic.Interaction.InputBox("InputBox Label", "Description");
if (string.IsNullOrWhiteSpace(MigrationName))
return "";
var MigrationVersion = System.DateTime.Now.ToString("yyyyMMddHHmm");
var MigrationFileName = MigrationVersion + "-" + MigrationName + ".sql";
var MigrationFilePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Host.TemplateFile), "", MigrationFileName));
#>
My T4 template goes here
<#
SaveOutput(MigrationFilePath);
IncludeInCurrentProject(MigrationFilePath)
.Open(Constants.vsViewKindPrimary)
.Activate();
#>
<#+
private void SaveOutput(string filename)
{
File.WriteAllText(filename, GenerationEnvironment.ToString());
GenerationEnvironment.Clear();
}
private ProjectItem IncludeInCurrentProject(string filename)
{
return CurrentProject.ProjectItems.AddFromFile(filename);
}
private Project CurrentProject
{
get
{
if (_currentProject == null) {
var serviceProvider = (IServiceProvider)this.Host;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
foreach(Project project in dte.Solution.Projects)
{
// workaround. dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject didn't work
string projectPath = project.FullName.Replace("\" + project.FileName, string.Empty);
if(Host.TemplateFile.Contains(projectPath))
{
_currentProject = project;
break;
}
}
}
return _currentProject;
}
}
private Project _currentProject;
#>
如何将生成的文件包含在与 T4 模板文件相同的文件夹中?
当您调用 IncludeInCurrentProject 时,输入应该是路径 + 文件名。
CurrentProject.ProjectItems
总是引用根中的 ProjectItems
。
我使用文件路径在 ProjectItems
中导航并调用了正确的 AddFromFile
。您可以检查 GetCurrentProjectItem
方法,此行为已在那里实现。
现在模板可以正常工作了:
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".sql" #>
<#@ assembly name="Microsoft.VisualBasic.dll" #>
<#@ assembly name="EnvDTE" #>
<#@ import Namespace="System.IO" #>
<#@ import Namespace="System.Text.RegularExpressions" #>
<#@ import namespace="EnvDTE" #>
<#
var migrationName = Microsoft.VisualBasic.Interaction.InputBox("InputBox Label", "Description");
Regex alphaNumericRegex = new Regex("[^a-zA-Z0-9-_]");
migrationName = alphaNumericRegex.Replace(migrationName, string.Empty);
if (string.IsNullOrWhiteSpace(migrationName))
return "";
var migrationVersion = System.DateTime.Now.ToString("yyyyMMddHHmm");
var migrationFileName = migrationVersion + "-InsertCourt" + migrationName + ".sql";
var migrationFilePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Host.TemplateFile), migrationFileName));
#>
My T4 template goes here
<#
SaveOutput(migrationFilePath);
IncludeInCurrentProject(migrationFilePath)
.Open(Constants.vsViewKindPrimary)
.Activate();
#>
<#+
private void SaveOutput(string filename)
{
File.WriteAllText(filename, GenerationEnvironment.ToString());
GenerationEnvironment.Clear();
}
private ProjectItem IncludeInCurrentProject(string filename)
{
ProjectItem item = GetCurrentProjectItem().ProjectItems.AddFromFile(filename);
item.Properties.Item("BuildAction").Value = "None";
return item;
}
private ProjectItem GetCurrentProjectItem()
{
var serviceProvider = (IServiceProvider)this.Host;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
string templateDirectory = Path.GetDirectoryName(Host.TemplateFile);
string foldersString = templateDirectory.Replace(Path.GetDirectoryName(GetCurrentProject().FullName), string.Empty);
string[] foldersArray = foldersString.Split(new [] {"\"}, StringSplitOptions.RemoveEmptyEntries);
foreach(Project project in dte.Solution.Projects)
{
ProjectItems currentProjectItems = null;
foreach(string folder in foldersArray)
{
if(currentProjectItems == null)
{
currentProjectItems = project.ProjectItems;
}
foreach(ProjectItem projectItem in currentProjectItems)
{
if(projectItem.Name == folder)
{
if(Array.IndexOf(foldersArray, folder) == foldersArray.Length - 1)
{
return projectItem;
}
currentProjectItems = projectItem.ProjectItems;
break;
}
}
}
}
return null;
}
private Project GetCurrentProject()
{
var serviceProvider = (IServiceProvider)this.Host;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
foreach(Project project in dte.Solution.Projects)
{
// workaround. dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject didn't work
string directory = Path.GetDirectoryName(project.FullName);
if(Host.TemplateFile.Contains(directory))
{
return project;
}
}
return null;
}
private ProjectItem _currentProjectItem;
#>
我正在尝试将保存的文件添加到我的 T4 模板文件的当前项目中。
SaveOutput
方法按预期保存了文件,但是当我使用 IncludeInCurrentProject
方法时,调用了 ProjectItems.AddFromFile
(docs here),然后文件被添加到项目的 root。
我想将 SaveOutput
方法生成的文件包含在项目的确切位置。
这是我现在拥有的:
这是我的 .tt 文件:
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".sql" #>
<#@ assembly name="Microsoft.VisualBasic.dll" #>
<#@ assembly name="EnvDTE" #>
<#@ import Namespace="System.IO" #>
<#@ import namespace="EnvDTE" #>
<#
var MigrationName = Microsoft.VisualBasic.Interaction.InputBox("InputBox Label", "Description");
if (string.IsNullOrWhiteSpace(MigrationName))
return "";
var MigrationVersion = System.DateTime.Now.ToString("yyyyMMddHHmm");
var MigrationFileName = MigrationVersion + "-" + MigrationName + ".sql";
var MigrationFilePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Host.TemplateFile), "", MigrationFileName));
#>
My T4 template goes here
<#
SaveOutput(MigrationFilePath);
IncludeInCurrentProject(MigrationFilePath)
.Open(Constants.vsViewKindPrimary)
.Activate();
#>
<#+
private void SaveOutput(string filename)
{
File.WriteAllText(filename, GenerationEnvironment.ToString());
GenerationEnvironment.Clear();
}
private ProjectItem IncludeInCurrentProject(string filename)
{
return CurrentProject.ProjectItems.AddFromFile(filename);
}
private Project CurrentProject
{
get
{
if (_currentProject == null) {
var serviceProvider = (IServiceProvider)this.Host;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
foreach(Project project in dte.Solution.Projects)
{
// workaround. dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject didn't work
string projectPath = project.FullName.Replace("\" + project.FileName, string.Empty);
if(Host.TemplateFile.Contains(projectPath))
{
_currentProject = project;
break;
}
}
}
return _currentProject;
}
}
private Project _currentProject;
#>
如何将生成的文件包含在与 T4 模板文件相同的文件夹中?
当您调用 IncludeInCurrentProject 时,输入应该是路径 + 文件名。
CurrentProject.ProjectItems
总是引用根中的 ProjectItems
。
我使用文件路径在 ProjectItems
中导航并调用了正确的 AddFromFile
。您可以检查 GetCurrentProjectItem
方法,此行为已在那里实现。
现在模板可以正常工作了:
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".sql" #>
<#@ assembly name="Microsoft.VisualBasic.dll" #>
<#@ assembly name="EnvDTE" #>
<#@ import Namespace="System.IO" #>
<#@ import Namespace="System.Text.RegularExpressions" #>
<#@ import namespace="EnvDTE" #>
<#
var migrationName = Microsoft.VisualBasic.Interaction.InputBox("InputBox Label", "Description");
Regex alphaNumericRegex = new Regex("[^a-zA-Z0-9-_]");
migrationName = alphaNumericRegex.Replace(migrationName, string.Empty);
if (string.IsNullOrWhiteSpace(migrationName))
return "";
var migrationVersion = System.DateTime.Now.ToString("yyyyMMddHHmm");
var migrationFileName = migrationVersion + "-InsertCourt" + migrationName + ".sql";
var migrationFilePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Host.TemplateFile), migrationFileName));
#>
My T4 template goes here
<#
SaveOutput(migrationFilePath);
IncludeInCurrentProject(migrationFilePath)
.Open(Constants.vsViewKindPrimary)
.Activate();
#>
<#+
private void SaveOutput(string filename)
{
File.WriteAllText(filename, GenerationEnvironment.ToString());
GenerationEnvironment.Clear();
}
private ProjectItem IncludeInCurrentProject(string filename)
{
ProjectItem item = GetCurrentProjectItem().ProjectItems.AddFromFile(filename);
item.Properties.Item("BuildAction").Value = "None";
return item;
}
private ProjectItem GetCurrentProjectItem()
{
var serviceProvider = (IServiceProvider)this.Host;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
string templateDirectory = Path.GetDirectoryName(Host.TemplateFile);
string foldersString = templateDirectory.Replace(Path.GetDirectoryName(GetCurrentProject().FullName), string.Empty);
string[] foldersArray = foldersString.Split(new [] {"\"}, StringSplitOptions.RemoveEmptyEntries);
foreach(Project project in dte.Solution.Projects)
{
ProjectItems currentProjectItems = null;
foreach(string folder in foldersArray)
{
if(currentProjectItems == null)
{
currentProjectItems = project.ProjectItems;
}
foreach(ProjectItem projectItem in currentProjectItems)
{
if(projectItem.Name == folder)
{
if(Array.IndexOf(foldersArray, folder) == foldersArray.Length - 1)
{
return projectItem;
}
currentProjectItems = projectItem.ProjectItems;
break;
}
}
}
}
return null;
}
private Project GetCurrentProject()
{
var serviceProvider = (IServiceProvider)this.Host;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
foreach(Project project in dte.Solution.Projects)
{
// workaround. dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject didn't work
string directory = Path.GetDirectoryName(project.FullName);
if(Host.TemplateFile.Contains(directory))
{
return project;
}
}
return null;
}
private ProjectItem _currentProjectItem;
#>