转 Multiple outputs from T4 made easy t4生成多文件
原文:http://damieng.com/blog/2009/11/06/multiple-outputs-from-t4-made-easy-revisited
Usage
Initialization
You’ll need to get the code into your template – either copy the code in or reference it with an include directive. Then declare an instance of the Manager class passing in some environmental options such as the desired default output path. (For Visual Studio 2010 remove the #v3.5 portion from the language attribute)
<#@ template language="C#v3.5" hostspecific="True"
#><#@include file="Manager.ttinclude"
#><# var manager = Manager.Create(Host, GenerationEnvironment); #>
File blocks
Then add one line before and one line after each block which could be split out into it’s own file passing in what the filename would be if split. The EndBlock is optional if you want it to carry through to the next one :)
<# manager.StartNewFile("Employee.generated.cs"); #>
public class Employee { … }
<# manager.EndBlock(); #>
Headers & footers
Many templates need to share a common header/footer for such things as comments or using/import statements or turning on/off warnings. Simply use StartHeader and StartFooter and the blocks will be emitted to the start and end of all split files as well as being left in the original output file.
<# manager.StartHeader(); #>
// Code generated by a template
using System; <# manager.EndBlock(); #>
Process
At the end of the template call Process to handle splitting the files (true) or not (false). Anything not included in a specific StartNewFile block will remain in the original output file.
<# manager.Process(true); #>
<#@ assembly name="System.Core"
#><#@ assembly name="System.Data.Linq"
#><#@ assembly name="EnvDTE"
#><#@ assembly name="System.Xml"
#><#@ assembly name="System.Xml.Linq"
#><#@ import namespace="System"
#><#@ import namespace="System.CodeDom"
#><#@ import namespace="System.CodeDom.Compiler"
#><#@ import namespace="System.Collections.Generic"
#><#@ import namespace="System.Data.Linq"
#><#@ import namespace="System.Data.Linq.Mapping"
#><#@ import namespace="System.IO"
#><#@ import namespace="System.Linq"
#><#@ import namespace="System.Reflection"
#><#@ import namespace="System.Text"
#><#@ import namespace="System.Xml.Linq"
#><#@ import namespace="Microsoft.VisualStudio.TextTemplating"
#><#+ // Manager class records the various blocks so it can split them up
class Manager {
private class Block {
public String Name;
public int Start, Length;
} private Block currentBlock;
private List<Block> files = new List<Block>();
private Block footer = new Block();
private Block header = new Block();
private ITextTemplatingEngineHost host;
private StringBuilder template;
protected List<String> generatedFileNames = new List<String>(); public static Manager Create(ITextTemplatingEngineHost host, StringBuilder template) {
return (host is IServiceProvider) ? new VSManager(host, template) : new Manager(host, template);
} public void StartNewFile(String name) {
if (name == null)
throw new ArgumentNullException("name");
CurrentBlock = new Block { Name = name };
} public void StartFooter() {
CurrentBlock = footer;
} public void StartHeader() {
CurrentBlock = header;
} public void EndBlock() {
if (CurrentBlock == null)
return;
CurrentBlock.Length = template.Length - CurrentBlock.Start;
if (CurrentBlock != header && CurrentBlock != footer)
files.Add(CurrentBlock);
currentBlock = null;
} public virtual void Process(bool split) {
if (split) {
EndBlock();
String headerText = template.ToString(header.Start, header.Length);
String footerText = template.ToString(footer.Start, footer.Length);
String outputPath = Path.GetDirectoryName(host.TemplateFile);
files.Reverse();
foreach(Block block in files) {
String fileName = Path.Combine(outputPath, block.Name);
String content = headerText + template.ToString(block.Start, block.Length) + footerText;
generatedFileNames.Add(fileName);
CreateFile(fileName, content);
template.Remove(block.Start, block.Length);
}
}
} protected virtual void CreateFile(String fileName, String content) {
if (IsFileContentDifferent(fileName, content))
File.WriteAllText(fileName, content);
} public virtual String GetCustomToolNamespace(String fileName) {
return null;
} public virtual String DefaultProjectNamespace {
get { return null; }
} protected bool IsFileContentDifferent(String fileName, String newContent) {
return !(File.Exists(fileName) && File.ReadAllText(fileName) == newContent);
} private Manager(ITextTemplatingEngineHost host, StringBuilder template) {
this.host = host;
this.template = template;
} private Block CurrentBlock {
get { return currentBlock; }
set {
if (CurrentBlock != null)
EndBlock();
if (value != null)
value.Start = template.Length;
currentBlock = value;
}
} private class VSManager: Manager {
private EnvDTE.ProjectItem templateProjectItem;
private EnvDTE.DTE dte;
private Action<String> checkOutAction;
private Action<IEnumerable<String>> projectSyncAction; public override String DefaultProjectNamespace {
get {
return templateProjectItem.ContainingProject.Properties.Item("DefaultNamespace").Value.ToString();
}
} public override String GetCustomToolNamespace(string fileName) {
return dte.Solution.FindProjectItem(fileName).Properties.Item("CustomToolNamespace").Value.ToString();
} public override void Process(bool split) {
if (templateProjectItem.ProjectItems == null)
return;
base.Process(split);
projectSyncAction.EndInvoke(projectSyncAction.BeginInvoke(generatedFileNames, null, null));
} protected override void CreateFile(String fileName, String content) {
if (IsFileContentDifferent(fileName, content)) {
CheckoutFileIfRequired(fileName);
File.WriteAllText(fileName, content);
}
} internal VSManager(ITextTemplatingEngineHost host, StringBuilder template)
: base(host, template) {
var hostServiceProvider = (IServiceProvider) host;
if (hostServiceProvider == null)
throw new ArgumentNullException("Could not obtain IServiceProvider");
dte = (EnvDTE.DTE) hostServiceProvider.GetService(typeof(EnvDTE.DTE));
if (dte == null)
throw new ArgumentNullException("Could not obtain DTE from host");
templateProjectItem = dte.Solution.FindProjectItem(host.TemplateFile);
checkOutAction = (String fileName) => dte.SourceControl.CheckOutItem(fileName);
projectSyncAction = (IEnumerable<String> keepFileNames) => ProjectSync(templateProjectItem, keepFileNames);
} private static void ProjectSync(EnvDTE.ProjectItem templateProjectItem, IEnumerable<String> keepFileNames) {
var keepFileNameSet = new HashSet<String>(keepFileNames);
var projectFiles = new Dictionary<String, EnvDTE.ProjectItem>();
var originalFilePrefix = Path.GetFileNameWithoutExtension(templateProjectItem.get_FileNames()) + ".";
foreach(EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems)
projectFiles.Add(projectItem.get_FileNames(), projectItem); // Remove unused items from the project
foreach(var pair in projectFiles)
if (!keepFileNames.Contains(pair.Key) && !(Path.GetFileNameWithoutExtension(pair.Key) + ".").StartsWith(
originalFilePrefix))
pair.Value.Delete(); // Add missing files to the project
foreach(String fileName in keepFileNameSet)
if (!projectFiles.ContainsKey(fileName))
templateProjectItem.ProjectItems.AddFromFile(fileName);
} private void CheckoutFileIfRequired(String fileName) {
var sc = dte.SourceControl;
if (sc != null && sc.IsItemUnderSCC(fileName) && !sc.IsItemCheckedOut(fileName))
checkOutAction.EndInvoke(checkOutAction.BeginInvoke(fileName, null, null));
}
}
} #>
转 Multiple outputs from T4 made easy t4生成多文件的更多相关文章
- Multiple outputs from T4 made easy – revisited » DamienG
Multiple outputs from T4 made easy – revisited » DamienG Multiple outputs from T4 made easy – revisi ...
- [转] How to generate multiple outputs from single T4 template (T4 输出多个文件)
本文转自:http://www.olegsych.com/2008/03/how-to-generate-multiple-outputs-from-single-t4-template/ Updat ...
- FluentData-新型轻量级ORM 利用T4模板 批量生成多文件 实体和业务逻辑 代码
FluentData,它是一个轻量级框架,关注性能和易用性. 下载地址:FlunenData.Model 利用T4模板,[MultipleOutputHelper.ttinclude]批量生成多文件 ...
- T4模板根据DB生成实体类
1.前言 为什么会有这篇文章了,最近看到了一些框架,里面要写的代码太多了,故此就想偷懒,要是能写出一个T4模板,在数据库添加表后,根据模板就可以自动生成了类文件了,这样多好,心动不如行动.记得使用T4 ...
- T4教程1 T4模版引擎之基础入门
T4模版引擎之基础入门 额,T4好陌生的名字,和NuGet一样很悲催,不为世人所熟知,却又在背后默默无闻的奉献着,直到现在我们项目组的人除了我之外,其它人还是对其豪无兴趣,基本上是连看一眼都懒得看 ...
- T4教程2 T4模版引擎之生成数据库实体类
T4模版引擎之生成数据库实体类 在通过T4模版引擎之基础入门 对T4有了初步印象后,我们开始实战篇.T4模板引擎可以当做一个代码生成器,代码生成器的职责当然是用来生成代码(这不是废话吗).而这其中 ...
- 使用T4为数据库自动生成实体类
T4 (Text Template Transformation Toolkit) 是一个基于模板的代码生成器.使用T4你可以通过写一些ASP.NET-like模板,来生成C#, T-SQL, XML ...
- c# 利用t4模板,自动生成Model类
我们在用ORM(比如dapper)的时候,很多时候都需要自己写Model层(当然也有很多orm框架自带了这种功能,比如ef),特别是表里字段比较多的时候,一个Model要写半天,而且Model如果用于 ...
- T4生成多文件时,不生成自己
如:我用的网上的生成多文件的一个include文件. 生成多文件时,默认会生成一个以自己名字命名的文件如: 有一个demo.tt文件,生成时会出来一个demo.cs文件(默认情况下) 解决方法: Fo ...
随机推荐
- 选择结构switch
1.选择结构switch switch 条件语句也是一种很常用的选择语句,它和if条件语句不同,它只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码.例如,在程序中使用数字1~7来表示星期一到 ...
- Fib数列2 费马小定理+矩阵乘法
题解: 费马小定理 a^(p-1)=1(mod p) 这里推广到矩阵也是成立的 所以我们可以对(2^n)%(p-1) 然后矩阵乘法维护就好了 模数较大使用快速乘
- PHP查询数据库较慢,nginx 超时 返回 504:Sorry, the page you are looking for is currently unavailable.
现象: PHP查询数据库较慢,大约 60s 后 nginx 返回 504:Sorry, the page you are looking for is currently unavailable. 检 ...
- seafile数据的备份与恢复
seafile数据备份包括MySQL数据备份与seafile,seahub数据备份两个部分.所以在备份的时候需要注意这一点. 我的存储底层用glusterfs数据共享,为了防止一台服务器宕机以后另一台 ...
- Spring Boot之 Controller 接收参数和返回数据总结(包括上传、下载文件)
一.接收参数(postman发送) 1.form表单 @RequestParam("name") String name 会把传递过来的Form表单中的name对应 ...
- php json_encode转换中文乱码
$arr = ["a"=>'范德萨似懂非懂']; echo json_encode($arr,JSON_UNESCAPED_UNICODE);
- 043 hive数据同步到mysql
一:意义 1.意义 如果可以实现这个功能,就可以使用spark代替sqoop,功能程序就实现这个功能. 二:hive操作 1.准备数据 启动hive 否则报错,因为在hive与spark集成的时候,配 ...
- SSL/TLS
為 授权计算机为 SSL/TLS 安全通道建立信任关系. ServicePointManager.ServerCertificateValidationCallback += (o, c, ch, e ...
- sql取逗号前后数据与批量修改某一字段某一值
sql取逗号后的值 SELECT SUBSTRING_INDEX(字段,) FROM 表名 sql取逗号前的值 SELECT SUBSTRING_INDEX(字段,) FROM 表名 批量修改 UPD ...
- 用 threading 写多线程服务器
import socket import threading server = socket.socket() server.bind(("127.0.0.1",8899)) se ...