2017-09-01 10 views
1

私はマルチ出力ファイルにソリューションフォルダに存在プロジェクトでファイルを作成にしようとしています、T4テンプレートのプロジェクトにファイルを作成する方法、tangible T4 Editor tutorialに基づく。ソリューションフォルダ(ない物理フォルダ)

私は私の溶液中で次のような構造を持っている:抜粋の

/// <summary> 
/// Marks the end of the last file if there was one, and starts a new 
/// and marks this point in generation as a new file. 
/// </summary> 
/// <param name="name">Filename</param> 
/// <param name="projectName">Name of the target project for the new file.</param> 
/// <param name="folderName">Name of the target folder for the new file.</param> 
/// <param name="fileProperties">File property settings in vs for the new File</param> 
public void StartNewFile(string name, string projectName = "", 
    string folderName = "", FileProperties fileProperties = null) 
{ 
    if (String.IsNullOrWhiteSpace(name) == true) 
    { 
     throw new ArgumentException("name"); 
    } 

    CurrentBlock = new Block 
    { 
     Name = name, 
     ProjectName = projectName, 
     FolderName = folderName, 
     FileProperties = fileProperties ?? new FileProperties() 
    }; 
} 

/// <summary> 
/// Produce the template output files. 
/// </summary> 
public virtual IEnumerable<OutputFile> Process(bool split = true) 
{ 
    var list = new List<OutputFile>(); 

    if (split) 
    { 
     EndBlock(); 

     var headerText = _generationEnvironment.ToString(header.Start, header.Length); 
     var footerText = _generationEnvironment.ToString(footer.Start, footer.Length); 
     files.Reverse(); 

     foreach (var block in files) 
     { 
      var outputPath = VSHelper.GetOutputPath(dte, block, 
       Path.GetDirectoryName(_textTransformation.Host.TemplateFile)); //<-- exception bubbled up here 
      var fileName = Path.Combine(outputPath, block.Name); 
      var content = this.ReplaceParameter(headerText, block) + 
       _generationEnvironment.ToString(block.Start, block.Length) + 
       footerText; 

      var file = new OutputFile 
      { 
       FileName = fileName, 
       ProjectName = block.ProjectName, 
       FolderName = block.FolderName, 
       FileProperties = block.FileProperties, 
       Content = content 
      }; 

      CreateFile(file); 
      _generationEnvironment.Remove(block.Start, block.Length); 

      list.Add(file);  
     } 
    } 

    projectSyncAction.EndInvoke(projectSyncAction.BeginInvoke(list, null, null)); 
    this.CleanUpTemplatePlaceholders(); 
    var items = VSHelper.GetOutputFilesAsProjectItems(this.dte, list); 
    this.WriteVsProperties(items, list); 

    if (this.IsAutoIndentEnabled == true && split == true) 
    { 
     this.FormatProjectItems(items); 
    } 

    this.WriteLog(list); 

    return list; 
} 

private void FormatProjectItems(IEnumerable<EnvDTE.ProjectItem> items) 
{ 
    foreach (var item in items) 
    { 
     this._textTransformation.WriteLine(
     VSHelper.ExecuteVsCommand(this.dte, item, "Edit.FormatDocument")); 
     this._textTransformation.WriteLine("//-> " + item.Name); 
    } 
} 

private void WriteVsProperties(IEnumerable<EnvDTE.ProjectItem> items, 
    IEnumerable<OutputFile> outputFiles) 
{ 
    foreach (var file in outputFiles) 
    { 
     var item = items 
      .Where(p => p.Name == Path.GetFileName(file.FileName)) 
      .FirstOrDefault(); 
     if (item == null) continue; 

     if (String.IsNullOrEmpty(file.FileProperties.CustomTool) == false) 
     { 
      VSHelper.SetPropertyValue(
       item, "CustomTool", file.FileProperties.CustomTool); 
     } 

     if (String.IsNullOrEmpty(file.FileProperties.BuildActionString) == false) 
     { 
      VSHelper.SetPropertyValue(
       item, "ItemType", file.FileProperties.BuildActionString); 
     } 
    } 
} 

private string ReplaceParameter(string text, Block block) 
{ 
    if (String.IsNullOrEmpty(text) == false) 
    { 
     text = text.Replace("$filename$", block.Name); 
    } 

    foreach (var item in block.FileProperties.TemplateParameter.AsEnumerable()) 
    { 
     text = text.Replace(item.Key, item.Value); 
    } 

    return text; 
} 

/// <summary> 
/// Write log to the default output file. 
/// </summary> 
/// <param name="list"></param> 
private void WriteLog(IEnumerable<OutputFile> list) 
{ 
    this._textTransformation.WriteLine("// Generated helper templates"); 
    foreach (var item in templatePlaceholderList) 
    { 
     this._textTransformation.WriteLine(
      "// " + this.GetDirectorySolutionRelative(item));   
    } 

    this._textTransformation.WriteLine("// Generated items"); 
    foreach (var item in list) 
    { 
     this._textTransformation.WriteLine(
      "// " + this.GetDirectorySolutionRelative(item.FileName)); 
    } 
} 

/// <summary> 
/// Removes old template placeholders from the solution. 
/// </summary> 
private void CleanUpTemplatePlaceholders()  
{ 
    string[] activeTemplateFullNames = this.templatePlaceholderList.ToArray(); 
    string[] allHelperTemplateFullNames = VSHelper.GetAllSolutionItems(this.dte) 
     .Where(p => 
      p.Name == VSHelper.GetTemplatePlaceholderName(this.templateProjectItem)) 
     .Select(p => VSHelper.GetProjectItemFullPath(p)) 
     .ToArray(); 

    var delta = allHelperTemplateFullNames.Except(activeTemplateFullNames).ToArray(); 

    var dirtyHelperTemplates = VSHelper.GetAllSolutionItems(this.dte) 
     .Where(p => delta.Contains(VSHelper.GetProjectItemFullPath(p))); 

    foreach (ProjectItem item in dirtyHelperTemplates) 
    { 
     if (item.ProjectItems != null) 
     { 
      foreach (ProjectItem subItem in item.ProjectItems) 
      { 
       subItem.Remove(); 
      } 
     } 

     item.Remove(); 
    } 
} 

protected virtual void CreateFile(OutputFile file) 
{ 
    if (this.CanOverrideExistingFile == false && File.Exists(file.FileName) == true) 
    { 
     return; 
    } 

    if (IsFileContentDifferent(file)) 
    { 
     CheckoutFileIfRequired(file.FileName); 
     File.WriteAllText(file.FileName, file.Content, this.Encoding); 
    } 
} 

protected bool IsFileContentDifferent(OutputFile file) 
{ 
    return !(File.Exists(file.FileName) && File.ReadAllText(file.FileName) == file.Content); 
} 

private void CheckoutFileIfRequired(string fileName) 
{ 
    if (dte.SourceControl == null 
     || !dte.SourceControl.IsItemUnderSCC(fileName) 
      || dte.SourceControl.IsItemCheckedOut(fileName)) 
    { 
     return; 
    } 

    // run on worker thread to prevent T4 calling back into VS 
    checkOutAction.EndInvoke(checkOutAction.BeginInvoke(fileName, null, null)); 
} 

パート2:VSHelperクラス

/T4Templates 
    - T4TemplateProject **<--- my T4 Project** 
/Common 
    -Project.NameSpace.Common **<--- Want to create file in here** 
/Services 
    -Project.NameSpace.Services **<--- And create file in here** 

私の出発点は、ttincludefileからの抜粋です。例外がどこで発生し、バブルアップしたかを示しました。あなたは、文字列を検索することができます<-- exception

public class VSHelper 
{ 
    /// <summary> 
    /// Execute Visual Studio commands against the project item. 
    /// </summary> 
    /// <param name="item">The current project item.</param> 
    /// <param name="command">The vs command as string.</param> 
    /// <returns>An error message if the command fails.</returns> 
    public static string ExecuteVsCommand(EnvDTE.DTE dte, EnvDTE.ProjectItem item, params string[] command) 
    { 
     if (item == null) 
     { 
      throw new ArgumentNullException("item"); 
     } 

     string error = String.Empty; 

     try 
     { 
      EnvDTE.Window window = item.Open(); 
      window.Activate(); 

      foreach (var cmd in command) 
      { 
       if (String.IsNullOrWhiteSpace(cmd) == true) 
       { 
        continue; 
       } 

       EnvDTE80.DTE2 dte2 = dte as EnvDTE80.DTE2; 
       dte2.ExecuteCommand(cmd, String.Empty);  
      } 

      item.Save(); 
      window.Visible = false; 
      // window.Close(); // Ends VS, but not the tab :(
     } 
     catch (Exception ex) 
     { 
      error = String.Format("Error processing file {0} {1}", item.Name, ex.Message); 
     } 

     return error; 
    } 

    /// <summary> 
    /// Sets a property value for the vs project item. 
    /// </summary> 
    public static void SetPropertyValue(EnvDTE.ProjectItem item, string propertyName, object value) 
    { 
     EnvDTE.Property property = item.Properties.Item(propertyName); 
     if (property == null) 
     { 
      throw new ArgumentException(String.Format("The property {0} was not found.", propertyName)); 
     } 
     else 
     { 
      property.Value = value; 
     } 
    } 

    public static IEnumerable<ProjectItem> GetOutputFilesAsProjectItems(EnvDTE.DTE dte, IEnumerable<OutputFile> outputFiles) 
    { 
     var fileNames = (from o in outputFiles 
         select Path.GetFileName(o.FileName)).ToArray(); 

     return VSHelper.GetAllSolutionItems(dte).Where(f => fileNames.Contains(f.Name)); 
    } 

    public static string GetOutputPath(EnvDTE.DTE dte, Block block, string defaultPath) 
    { 
     if (String.IsNullOrEmpty(block.ProjectName) == true && String.IsNullOrEmpty(block.FolderName) == true) 
     { 
      return defaultPath; 
     } 

     EnvDTE.Project prj = null; 
     EnvDTE.ProjectItem item = null; 

     if (String.IsNullOrEmpty(block.ProjectName) == false) 
     { 
      prj = GetProject(dte, block.ProjectName); //<-- exception bubbled up here   
     } 

     if (String.IsNullOrEmpty(block.FolderName) == true && prj != null) 
     { 
      return Path.GetDirectoryName(prj.FullName); 
     } 
     else if (prj != null && String.IsNullOrEmpty(block.FolderName) == false) 
     { 
      item = GetAllProjectItemsRecursive(prj.ProjectItems).Where(i=>i.Name == block.FolderName).First(); 
     } 
     else if (String.IsNullOrEmpty(block.FolderName) == false) 
     { 
      item = GetAllProjectItemsRecursive(
       dte.ActiveDocument.ProjectItem.ContainingProject.ProjectItems). 
       Where(i=>i.Name == block.FolderName).First(); 
     } 

     if (item != null) 
     { 
      return GetProjectItemFullPath(item); 
     } 

     return defaultPath; 
    } 
    public static string GetTemplatePlaceholderName(EnvDTE.ProjectItem item) 
    { 
     return String.Format("{0}.txt4", Path.GetFileNameWithoutExtension(item.Name)); 
    } 

    public static EnvDTE.ProjectItem GetTemplateProjectItem(EnvDTE.DTE dte, OutputFile file, EnvDTE.ProjectItem defaultItem) 
    { 
     if (String.IsNullOrEmpty(file.ProjectName) == true && String.IsNullOrEmpty(file.FolderName) == true) 
     { 
      return defaultItem; 
     } 

     string templatePlaceholder = GetTemplatePlaceholderName(defaultItem); 
     string itemPath = Path.GetDirectoryName(file.FileName); 
     string fullName = Path.Combine(itemPath, templatePlaceholder); 
     EnvDTE.Project prj = null; 
     EnvDTE.ProjectItem item = null; 

     if (String.IsNullOrEmpty(file.ProjectName) == false) 
     { 
      prj = GetProject(dte, file.ProjectName);    
     } 

     if (String.IsNullOrEmpty(file.FolderName) == true && prj != null) 
     { 
      return FindProjectItem(prj.ProjectItems, fullName, true); 
     } 
     else if (prj != null && String.IsNullOrEmpty(file.FolderName) == false) 
     { 
      item = GetAllProjectItemsRecursive(prj.ProjectItems).Where(i=>i.Name == file.FolderName).First(); 
     } 
     else if (String.IsNullOrEmpty(file.FolderName) == false) 
     { 
      item = GetAllProjectItemsRecursive(
       dte.ActiveDocument.ProjectItem.ContainingProject.ProjectItems). 
       Where(i=>i.Name == file.FolderName).First(); 
     } 

     if (item != null) 
     { 
      return FindProjectItem(item.ProjectItems, fullName, true); 
     } 

     return defaultItem; 
    } 

    private static EnvDTE.ProjectItem FindProjectItem(EnvDTE.ProjectItems items, string fullName, bool canCreateIfNotExists) 
    { 
     EnvDTE.ProjectItem item = (from i in items.Cast<EnvDTE.ProjectItem>() 
            where i.Name == Path.GetFileName(fullName) 
            select i).FirstOrDefault(); 
     if (item == null) 
     { 
      File.CreateText(fullName); 
      item = items.AddFromFile(fullName); 
     } 

     return item; 
    } 

    public static EnvDTE.Project GetProject(EnvDTE.DTE dte, string projectName) 
    { 
     return GetAllProjects(dte).Where(p=>p.Name == projectName).First(); // <-- exception ORIGINATES HERE 
    } 

    public static IEnumerable<EnvDTE.Project> GetAllProjects(EnvDTE.DTE dte) 
    { 
     List<EnvDTE.Project> projectList = new List<EnvDTE.Project>(); 

     var folders = dte.Solution.Projects.Cast<EnvDTE.Project>().Where(p=>p.Kind == EnvDTE80.ProjectKinds.vsProjectKindSolutionFolder); 

     foreach (EnvDTE.Project folder in folders) 
     { 
      if (folder.ProjectItems == null) continue; 

      foreach (EnvDTE.ProjectItem item in folder.ProjectItems) 
      { 
       if (item.Object is EnvDTE.Project) 
        projectList.Add(item.Object as EnvDTE.Project); 
      } 
     } 

     var projects = dte.Solution.Projects.Cast<EnvDTE.Project>().Where(p=>p.Kind != EnvDTE80.ProjectKinds.vsProjectKindSolutionFolder); 

     if (projects.Count() > 0) 
      projectList.AddRange(projects); 

     return projectList; 
    } 

    public static EnvDTE.ProjectItem GetProjectItemWithName(EnvDTE.ProjectItems items, string itemName) 
    { 
     return GetAllProjectItemsRecursive(items).Cast<ProjectItem>().Where(i=>i.Name == itemName).First(); 
    } 

    public static string GetProjectItemFullPath(EnvDTE.ProjectItem item) 
    { 
     return item.Properties.Item("FullPath").Value.ToString(); 
    } 

    public static IEnumerable<EnvDTE.ProjectItem> GetAllSolutionItems(EnvDTE.DTE dte) 
    { 
     List<EnvDTE.ProjectItem> itemList = new List<EnvDTE.ProjectItem>(); 

     foreach (Project item in GetAllProjects(dte)) 
     { 
      if (item == null || item.ProjectItems == null) continue; 

      itemList.AddRange(GetAllProjectItemsRecursive(item.ProjectItems)); 
     } 

     return itemList; 
    } 

    public static IEnumerable<EnvDTE.ProjectItem> GetAllProjectItemsRecursive(EnvDTE.ProjectItems projectItems) 
    { 
     foreach (EnvDTE.ProjectItem projectItem in projectItems) 
     { 
      if (projectItem.ProjectItems == null) continue; 

      foreach (EnvDTE.ProjectItem subItem in GetAllProjectItemsRecursive(projectItem.ProjectItems)) 
      { 
       yield return subItem; 
      } 


      yield return projectItem; 
     } 
    } 
} 

マイテンプレート:私は次のエラーを取得

<#@ template debug="true" hostSpecific="true" #> 
<#@ output extension=".cs" #> 
<#@ Assembly Name="System.Core" #> 
<#@ Assembly Name="System.Windows.Forms" #> 
<#@ import namespace="System" #> 
<#@ import namespace="System.IO" #> 
<#@ import namespace="System.Diagnostics" #> 
<#@ import namespace="System.Linq" #> 
<#@ import namespace="System.Collections" #> 
<#@ import namespace="System.Collections.Generic" #> 

<#@ include file="TemplateFileManagerV2.1.ttinclude" #> 
<# 
var manager = TemplateFileManager.Create(this); 
#> 

<# 
//This correctly generates a file in the local T4TemplateProject 
manager.StartNewFile("MyObject.cs"); 
#> 

<# 
//this fails 
manager.StartNewFile("MyObjectDto.cs","Project.NameSpace.Common","Common"); 
#> 

<#  
manager.Process(); 
#> 

    Severity Code Description Project File Line Suppression State Error Running transformation: System.InvalidOperationException: Sequence contains no elements

    は、私は、次の読んだことがあります

  1. http://t4-editor.tangible-engineering.com/blog/how-to-generate-multiple-output-files-from-a-single-t4-template.html
  2. How to create multiple output files from a single T4 template using Tangible Editor?

T4の例は、以下の溶液構造に基づいています。 enter image description here

私はソリューションフォルダが存在する場合に同じことをしたいと思います: enter image description here

+0

どの行からその例外がスローされるのでしょうか?また、CreateFile()のコードを投稿することができます –

+0

CreatFile()コードとその依存関係を更新しました – user919426

+0

例外をスローする行については、許容行数を超えてコードを分割する必要があります – user919426

答えて

1

私はあなたのコードの関連する部分をこれまでに減らしました:

var projectList = dte.Solution.Projects 
    .Cast<EnvDTE.Project>() 
    .Where(p => p.Kind == EnvDTE80.ProjectKinds.vsProjectKindSolutionFolder) 
    .Where(folder => folder.ProjectItems != null) 
    .SelectMany(folder => folder.ProjectItems) 
    .Where(item => item.Object is EnvDTE.Project) 
    .Select(item => item.Object as EnvDTE.Project) 

var projects = dte.Solution.Projects.Cast<EnvDTE.Project>() 
    .Where(p => p.Kind != EnvDTE80.ProjectKinds.vsProjectKindSolutionFolder); 

projectList.Concat(projects) 
    .Where(p=>p.Name == projectName) 
    .First(); // <-- exception ORIGINATES HERE 

したがって、p.Kindまたはp.Nameのいずれかが期待どおりではないようです。

これをデバッグするには、dte.Solution.Projectsとすべての子ProjectItemを繰り返します。種類と名前のプロパティを出力します。

+0

すぐに試してみます。どちらの方法でも、すべてのコードを実行して、尋ねてそれを理解しようとしてくれてありがとう! – user919426

関連する問題