Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将T4生成的文件包含在模板文件的同一文件夹中_C#_Visual Studio_T4 - Fatal编程技术网

C# 将T4生成的文件包含在模板文件的同一文件夹中

C# 将T4生成的文件包含在模板文件的同一文件夹中,c#,visual-studio,t4,C#,Visual Studio,T4,我正在尝试将保存的文件添加到T4模板文件的当前项目中。 文件按预期通过SaveOutput方法保存,但当我使用IncludeInCurrentProject方法时,该方法调用ProjectItems.AddFromFile(),然后将文件添加到项目的根 我希望将由SaveOutput方法生成的文件包含在项目的确切位置上 这就是我现在拥有的: 这是我的.tt文件: <#@ template debug="true" hostspecific="true" language="C#" #&g

我正在尝试将保存的文件添加到T4模板文件的当前项目中。 文件按预期通过
SaveOutput
方法保存,但当我使用
IncludeInCurrentProject
方法时,该方法调用
ProjectItems.AddFromFile
(),然后将文件添加到项目的

我希望将由
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模板在这里

你好,佩德罗。MigrationFilePath包含完整路径(路径+文件名),此变量发送到IncludeInCurrentProject方法。请在此查看:并根据您的需要进行调整。因此,我也在此处将每个输出写入不同的项目和文件夹:我遇到了完全相同的问题,但在从另一个项目创建文件时遇到了同样的问题。我用了你的文件夹循环解决方案,效果很好。谢谢@安德里亚,我很高兴这个解决方案对你有所帮助。