本文转自:http://damieng.com/blog/2009/01/22/multiple-outputs-from-t4-made-easy

One of the things I wanted my LINQ to SQL T4 templates to do was be able to split the output into a file-per-entity. Existing solutions used either a separate set of templates with duplicate code or intrusive handling code throughout the template. Here’s my helper class to abstract the problem away from what is already complicated enough template code.

Using the Manager class

Setup

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.

<#@ template language="C#v3.5" hostspecific="True"
#><#@ include file="Manager.ttinclude"
#><# var manager = new Manager(Host, GenerationEnvironment, true) { OutputPath = Path.GetDirectoryName(Host.TemplateFile) }; #>

Define a block

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.

<# manager.StartBlock("Employee.generated.cs"); #>
public class Employee { … }
<# manager.EndBlock(); #>

Headers and 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/EndHeader and StartFooter/EndFooter. The resulting blocks will be emitted into all split files and left in the original output too.

<# manager.StartHeader(); #>
// Code generated template
using System;<# manager.EndHeader(); #>

Process

At the end of the template call Process to handle splitting the files (true) or not (false). Anything not included in a specific start/end block will remain in the original output file.

<# manager.Process(true); #>

When processing each block name in the Output path will either be overwritten or deleted to enable proper clean-up. It will also add and remove the files from Visual Studio somake sure your generated names aren’t going to collide with hand-written ones!

Manager classes

Here is the Manger class itself as well as the small ManagementStrategy classes that determines what to do with the files within Visual Studio (add/remove project items) and outside of Visual Studio (create/delete files).

Download Manager.ttinclude (4KB)

Licensed under the Microsoft Public License (MS-PL)
<#@ assembly name="System.Core"
#><#@ assembly name="EnvDTE"
#><#@ import namespace="System.Collections.Generic"
#><#@ import namespace="System.IO"
#><#@ import namespace="System.Text"
#><#@ import namespace="Microsoft.VisualStudio.TextTemplating"
#><#+// T4 Template Block manager for handling multiple file outputs more easily.
// Copyright (c) Microsoft Corporation.  All rights reserved.
// This source code is made available under the terms of the Microsoft Public License (MS-PL)// Manager class records the various blocks so it can split them up
class Manager
{private struct Block {public String Name;public int Start, Length;}private List<Block> blocks = new List<Block>();private Block currentBlock;private Block footerBlock = new Block();private Block headerBlock = new Block();private ITextTemplatingEngineHost host;private ManagementStrategy strategy;private StringBuilder template;public String OutputPath { get; set; }public Manager(ITextTemplatingEngineHost host, StringBuilder template, bool commonHeader) {this.host = host;this.template = template;OutputPath = String.Empty;strategy = ManagementStrategy.Create(host);}public void StartBlock(String name) {currentBlock = new Block { Name = name, Start = template.Length };}public void StartFooter() {footerBlock.Start = template.Length;}public void EndFooter() {footerBlock.Length = template.Length - footerBlock.Start;}public void StartHeader() {headerBlock.Start = template.Length;}public void EndHeader() {headerBlock.Length = template.Length - headerBlock.Start;}    public void EndBlock() {currentBlock.Length = template.Length - currentBlock.Start;blocks.Add(currentBlock);}public void Process(bool split) {String header = template.ToString(headerBlock.Start, headerBlock.Length);String footer = template.ToString(footerBlock.Start, footerBlock.Length);blocks.Reverse();foreach(Block block in blocks) {String fileName = Path.Combine(OutputPath, block.Name);if (split) {String content = header + template.ToString(block.Start, block.Length) + footer;strategy.CreateFile(fileName, content);template.Remove(block.Start, block.Length);} else {strategy.DeleteFile(fileName);}}}
}class ManagementStrategy
{internal static ManagementStrategy Create(ITextTemplatingEngineHost host) {return (host is IServiceProvider) ? new VSManagementStrategy(host) : new ManagementStrategy(host);}internal ManagementStrategy(ITextTemplatingEngineHost host) { }internal virtual void CreateFile(String fileName, String content) {File.WriteAllText(fileName, content);}internal virtual void DeleteFile(String fileName) {if (File.Exists(fileName))File.Delete(fileName);}
}class VSManagementStrategy : ManagementStrategy
{private EnvDTE.ProjectItem templateProjectItem;internal VSManagementStrategy(ITextTemplatingEngineHost host) : base(host) {IServiceProvider hostServiceProvider = (IServiceProvider)host;if (hostServiceProvider == null)throw new ArgumentNullException("Could not obtain hostServiceProvider");EnvDTE.DTE 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);}internal override void CreateFile(String fileName, String content) {base.CreateFile(fileName, content);((EventHandler)delegate { templateProjectItem.ProjectItems.AddFromFile(fileName); }).BeginInvoke(null, null, null, null);}internal override void DeleteFile(String fileName) {((EventHandler)delegate { FindAndDeleteFile(fileName); }).BeginInvoke(null, null, null, null);}private void FindAndDeleteFile(String fileName) {foreach(EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems) {if (projectItem.get_FileNames(0) == fileName) {projectItem.Delete();return;}}}
}#>

[转]Multiple outputs from T4 made easy相关推荐

  1. 粗读MixMo: Mixing Multiple Inputs for Multiple Outputs via Deep Subnetworks

    在之前的研究中,有人提出可以把多个不同的网络集成到一个网络里,实现多输入和多输出,即一次输出好几张图,且一次输出这些图对应的结果,如分类结果. 之前的研究是把两幅图片各自乘以一个系数,融为一张图片,系 ...

  2. .net关于T4代码生成摸版的使用(.tt文件)

    1.目的:为了能 快速生成有规律的内容 文件 2.新建文本摸版文件.tt 3.写入如下代码,然后保存文件就会在正文下生成下面定义的文件 4. tt文件 /*T4代码生成模块的使用*/ <#@ o ...

  3. rstudio 管道符号_R中的管道指南

    rstudio 管道符号 R基础知识 (R Fundamentals) Data analysis often involves many steps. A typical journey from ...

  4. tensorflow: slim

    最近需要使用slim模块,用到哪里翻译哪里.原文及译文用正体,个人收获用斜体加下划线. slim的github readme:https://github.com/tensorflow/tensorf ...

  5. (转)Let’s make a DQN 系列

    Let's make a DQN 系列 Let's make a DQN: Theory September 27, 2016DQN This article is part of series Le ...

  6. 远程连接 错误 内部错误_关于错误的性质和原因。 了解错误因素

    远程连接 错误 内部错误 Back in 2012, I was a young[er] product designer working in a small tech agency in Vale ...

  7. MapReduce单元测试(MRunit)

    问题 借鉴 https://blog.csdn.net/sunshine920103/article/details/61615948 https://www.cnblogs.com/xdlaoliu ...

  8. Theano简单入门(一):Theano与Lasagne的安装

    一.介绍 Theano是一个Python库,专门用于定义.优化.求值数学表达式,效率高,适用于多维数组.特别适合做机器学习.一般来说,使用时需要安装python和numpy. 首先回顾一下机器学习的东 ...

  9. Theano深度学习框架之Lasagne安装及入门

    1.Lasagne简单介绍 lasagne意味千层饼,是基于theano之上主要用于建立和训练神经网络的深度学习库.Lasagne is a lightweight library to build ...

最新文章

  1. Spring是怎样诞生的?
  2. 锁相环环路滤波器计算公式_锁相环计算方法
  3. 进程间通信:消息队列概念及代码
  4. rdd转换成java数据结构_如何将CSV文件转换为RDD
  5. Atitit  数据存储的分组聚合 groupby的实现attilax总结
  6. SOFAStack的前世今生
  7. 7805引脚图及稳压电路图资料
  8. [转载]在 WPF 專案中開啟 Blend
  9. 主要省份城市的DNS服务器地址
  10. mongodb 的进库操作
  11. 本地远程查看服务器tomcat 上虚拟机信息
  12. map 详解(C++)
  13. 利用JSP编程技术实现一个简单的购物车程序
  14. 如何设置迪文DGUS屏的字体效果?
  15. Case when的用法
  16. 人工智能python营_AI人工智能训练营
  17. 用JS实现视频播放器
  18. java smali_如何把java代码转换成smali代码
  19. 要重复多少次变成潜意识_潜意识成功法则
  20. [SpriteKit] 制作瓦片地图小游戏

热门文章

  1. svg 线条动画浅尝
  2. AS 中 Plugin for Gradle 和 Gradle 之间的版本对应关系
  3. [SDOI2015]约数个数和
  4. 非常详细的Exchange 功能路线图
  5. 文件系统管理相关命令
  6. 【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记24 popovers弹窗
  7. 回顾2012;展望2013
  8. php建一个表按删除就删除,php怎样删除数据库表_后端开发
  9. [BZOJ4671]异或图
  10. C#构造函数、操作符重载以及自定义类型转换