t4 加载文件到解决方案
Use EnvDTE add/remove multiple files to project
Project Source
Source: EnvDTEManipulate
Licence: MIT
EnvDTE is an assembly-wrapped COM library containing the objects and members for Visual Studio core automation.
It’s widely used in Visual Studio Plugins to provide ability manipulate visual studio functionalities.
By using EnvDTE inside TextTemplate, we can create a easy solution for massive file creation.
Usage
First you need include EnvDTE into TextTemplate
<#@ assembly name="EnvDTE" #> <#@ import namespace="EnvDTE" #>
Also, you need to set the hostspecific to « true ».
<#@ template debug="false" hostspecific="true" language="C#" #>
This will allow you to use ITextTemplateEngineHost instance(Host), which allows you to access current TextTemplate instance.
Then using following code to obtain an instance of EnvDTE.DTE
var host = this.Host; //ITextTemplateEngineHost var serviceProvider = (IServiceProvider)host; //Convert Host to IServiceProvider var dte = (EnvDTE.DTE)serviceProvider.GetService(typeof(EnvDTE.DTE)); //Using IServiceProvider to get instance for EnvDTE
Get current solution
///<summary> /// Get current solution instance /// http://msdn.microsoft.com/en-us/library/envdte.solution_members(v=vs.90).aspx ///</summary> EnvDTE.Solution getCurrentSolution(DTE dte) { return dte.Solution; }
Get project item of text template file
///<summary> /// Get project item of this text template file /// http://msdn.microsoft.com/en-us/library/envdte.projectitem_members(v=vs.90).aspx ///</summary> EnvDTE.ProjectItem getProjectItemOfThisTextTemplate(DTE dte) { return dte.Solution.FindProjectItem(this.Host.TemplateFile); }
Get current project
EnvDTE.Project getCurrentProject(DTE dte) { return getProjectItemOfThisTextTemplate(dte).ContainingProject; }
Add subitem under project text template
void addSubItem(DTE dte, string path) { var item = getProjectItemOfThisTextTemplate(dte); //item.Collection //http://msdn.microsoft.com/fr-fr/library/envdte.projectitems_members(v=vs.90).aspx //Using add from template to add sub item into Text Template item.ProjectItems.AddFromTemplate(this.Host.TemplateFile, path); }
Clear all subitems under current text template file
void clearTextTemplateGeneratedItems(DTE dte, bool deleteDiskFile = false) { var item = getProjectItemOfThisTextTemplate(dte); //item.Collection only provides insertion functions. foreach(ProjectItem subItem in item.ProjectItems) { File.Delete(subItem.FileNames[1]); subItem.Delete(); } }
Example
Create class file and sql file from xml file: Models.xml
<?xml version="1.0" encoding="utf-8" ?> <Models> <Model name="MyUser"> <Property name="FirstName" type="string"></Property> <Property name="LastName" type="string"></Property> </Model> <Model name="MyGroup"> <Property name="Name" type="string"></Property> </Model> </Models>
Create models for this xml structure:
class Model { public string name { get; private set; } public IReadOnlyList properties { get; private set; } public Model(XmlNode node) { if(node.Attributes["name"]!=null) name = node.Attributes["name"].Value; var properties = new List(); foreach(XmlNode subNode in node.SelectNodes("Property")) { properties.Add(new Property(subNode)); } this.properties = properties; } } class Property { public string name { get; private set; } public string type { get; private set; } public Property(XmlNode node) { if(node.Attributes["name"]!=null) name = node.Attributes["name"].Value; if(node.Attributes["type"]!=null) type = node.Attributes["type"].Value; } public string getSqlType() { if(type=="string") return "nvarchar(100)"; return "ERROR:"+type+""; } }
Using XmlDocument class load xml file:
XmlDocument doc = new XmlDocument(); doc.Load(this.Host.ResolvePath("Models.xml")); this.clearTextTemplateGeneratedItems(dte, true); List models = new List(); foreach(XmlNode node in doc.SelectNodes("/Models/Model")) models.Add(new Model(node));
Then generate class file from Models
///<summary> /// Generate csharp class files ///</summary> void GenerateClassFile(DTE dte, IEnumerable models) { foreach(Model m in models) { #> public class <#= m.name #> { <#+ foreach(var p in m.properties) { #> public <#= p.type #> <#= p.name #> { get; set; } <#+ } #> } <#+ var filePath = Host.ResolvePath("") + "\\" + m.name + ".cs"; //attention, file path must use "\" not "/" using(StreamWriter w = File.CreateText(filePath)) { //Write the code generated to file w.WriteLine(this.GenerationEnvironment.ToString()); //Empty the code generated this.GenerationEnvironment.Remove(0, this.GenerationEnvironment.Length); } //Add item to solution this.addProjectItem(dte,filePath); } }
And generate SQL files from Models
///<summary> /// Generate SQL files ///</summary> void GenerateSQLFile(DTE dte, IEnumerable models) { foreach(Model m in models) { #> CREATE TABLE <#= m.name #> ( <#+ foreach(var p in m.properties) { #> <#= p.name #> <#= p.getSqlType() #> <#+ } #> ) <#+ var filePath = Host.ResolvePath("") + "\\" + m.name + ".sql"; //attention, file path must use "\" not "/" using(StreamWriter w = File.CreateText(filePath)) { //Write the code generated to file w.WriteLine(this.GenerationEnvironment.ToString()); //Empty the code generated this.GenerationEnvironment.Remove(0, this.GenerationEnvironment.Length); } //Add item to solution this.addProjectItem(dte,filePath); } }
转自 :http://shengjieinsight.com/blog/2013/12/use-envdte-addremove-multiple-files-to-project/