DW123

t4 加载文件到解决方案

Use EnvDTE add/remove multiple files to project

By admin | décembre 17, 2013

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/

posted on 2015-12-05 22:32  fw123  阅读(490)  评论(0编辑  收藏  举报

导航