我已经构建了一个t4模板来输出多个文件,但是我需要这些文件作为嵌入内容。
t4 是否提供开箱即用的方法?
如果没有,是否可以通过将每个文件的
<Content>
元素切换为<EmbeddedResource>
元素来修改项目文件?
以下是我将
ProjectItem
设置为嵌入式资源的方法:在 T4 模板中,我有一个函数接受 Project
对象和一个代表 T4 模板本身的 FileInfo
对象 - 可能有更简单的方法,但我使用...获得模板FileInfo
var templateFileInfo = new FileInfo(this.Host.TemplateFile);
使用模板
FileInfo
是因为我们需要生成的文件(我的T4模板输出多个文件),这些文件是在解决方案的模板文件“下”生成的。
[真的,我想要的是一个代表模板的
ProjectItem
,这样我就可以遍历自动生成的孩子。如果有更好的方法,请发表评论。]
一旦我有了代表每个 T4 生成文件的
ProjectItem
对象,我将枚举每个 Properties
集合,直到找到该 "BuildAction"
的 ProjectItem
属性;然后使用常量将其设置为“嵌入式资源”。
private void SetGeneratedFilesAsEmbeddedResources(Project project, FileInfo templateFileInfo)
{
const string propBuildAction = "BuildAction";
var generatedProjectItems = GetGeneratedProjectItems(project, templateFileInfo).ToList();
foreach (var generatedProjectItem in generatedProjectItems)
{
var props = generatedProjectItem.Properties;
if ((VSLangProj.prjBuildAction)props.Item(propBuildAction).Value != VSLangProj.prjBuildAction.prjBuildActionEmbeddedResource)
{
props.Item(propBuildAction).Value = VSLangProj.prjBuildAction.prjBuildActionEmbeddedResource;
}
}
}
private IEnumerable<ProjectItem> GetGeneratedProjectItems(Project project, FileInfo templateFileInfo)
{
var templateParentFolder = GetTemplateParentFolder(project, templateFileInfo);
foreach (ProjectItem item in templateParentFolder.ProjectItems)
{
if (item.Kind != EnvDTE.Constants.vsProjectItemKindPhysicalFile || item.Name != templateFileInfo.Name)
{
continue;
}
foreach (ProjectItem generatedItem in item.ProjectItems)
{
yield return generatedItem;
}
}
}
private ProjectItem GetTemplateParentFolder(Project project, FileInfo templateFileInfo)
{
var containingFolderName = templateFileInfo.Directory.Name;
foreach (ProjectItem item in project.ProjectItems)
{
if (item.Kind == EnvDTE.Constants.vsProjectItemKindPhysicalFolder && item.Name == containingFolderName)
{
return item;
}
}
throw new Exception($"Cannot execute {templateFileInfo.Name} - Unable to locate the \"{containingFolderName}\" folder at the root level.");
}