Set output of t4 template as embedded resource

56 views Asked by At

I've built a t4 template to output multiple files, but I need these files to be embedded content.

Does t4 offer an out-of-the-box method of doing this?

If not, might it be possible to modify the project file by switching each file's <Content> element to an <EmbeddedResource> element?

1

There are 1 answers

0
awj On BEST ANSWER

Here's how I set a ProjectItem to be an embedded resource: In the T4 template I have a function which takes the Project object and a FileInfo object representing the T4 template itself - there may be a simpler method but I obtained the template FileInfo using...

var templateFileInfo = new FileInfo(this.Host.TemplateFile);

The template FileInfo is used because we need the generated files (my T4 template outputs multiple files) which are generated 'under' the template file in the solution.

[Really, what I want here is a ProjectItem representing the template, so that I can loop over the auto-generated children. If there's a better way of doing this, please comment.]

Once I have the ProjectItem objects representing each of the T4-generated files, I enumerate each Properties collection until I find the "BuildAction" property for that ProjectItem; this is then set as "Embedded Resource" using a constant.

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.");
}