我想使用T4模板创建多个文件。因此,我正在使用TemplateFileManagerV2.1.ttinclude
文件来执行此操作。在TextTemplatingFileGenerator
模式(设计时间)下,它可以正常工作。我需要运行时生成,因此我将模式更改为TextTemplatingFilePreprocessor
。现在我的程序抛出NullReferenceException
进一步调试后,我发现在TextTemplatingFilePreprocessor
模式下不能正确创建TextTemplate实例。
如何在TemplateFileManager
模式下使用TextTemplatingFilePreprocessor
?
Template1.tt
<#@ template language="C#" debug="true" hostSpecific="true" #>
<#@ output extension=".cs" #>
<#@ include file="TemplateFileManagerV2.1.ttinclude" #>
<#@ 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" #>
<#
string Greeting = "Hello";
var manager = TemplateFileManager.Create(this);
manager.StartNewFile(Path.Combine(Path.GetDirectoryName(this.Host.TemplateFile), "Outputfile2.cs"));
#>
namespace MyNameSpace{
class MyGeneratedClass{
static void main (string[] args){
System.Console.WriteLine("<#= Greeting #>, the time is now: <#= System.DateTime.Now.ToString() #>");
}
}
}
<#
manager.Process();
#>
运行T4模板的代码
var page = new Template1();
var pageContent = page.TransformText();
手动设置Host
。现在Host.AsIServiceProvider()
返回null
public class TextTemplatingEngineHost : ITextTemplatingEngineHost
{
internal string TemplateFileValue;
public string TemplateFile
{
get { return TemplateFileValue; }
}
public string FileExtension { get; private set; } = ".cs";
public Encoding FileEncoding { get; private set; } = Encoding.UTF8;
public CompilerErrorCollection Errors { get; private set; }
public IList<string> StandardAssemblyReferences
{
get
{
return new string[]
{
typeof(System.Windows.Forms.AccessibleEvents).Assembly.Location
};
}
}
public IList<string> StandardImports
{
get
{
return new string[]
{
"System",
"System.IO",
"System.Diagnostics",
"System.Linq",
"System.Collections",
"System.Collections.Generic"
};
}
}
public bool LoadIncludeText(string requestFileName, out string content, out string location)
{
content = string.Empty;
location = string.Empty;
if (File.Exists(requestFileName))
{
content = File.ReadAllText(requestFileName);
return true;
}
else
{
return false;
}
}
public object GetHostOption(string optionName)
{
object returnObject;
switch (optionName)
{
case "CacheAssemblies":
returnObject = true;
break;
default:
returnObject = null;
break;
}
return returnObject;
}
public string ResolveAssemblyReference(string assemblyReference)
{
if (File.Exists(assemblyReference))
{
return assemblyReference;
}
string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), assemblyReference);
if (File.Exists(candidate))
{
return candidate;
}
return "";
}
public Type ResolveDirectiveProcessor(string processorName)
{
if (string.Compare(processorName, "XYZ", StringComparison.OrdinalIgnoreCase) == 0)
{
//return typeof();
}
throw new Exception("Directive Processor not found");
}
public string ResolvePath(string fileName)
{
if (fileName == null)
{
throw new ArgumentNullException("the file name cannot be null");
}
if (File.Exists(fileName))
{
return fileName;
}
string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), fileName);
if (File.Exists(candidate))
{
return candidate;
}
return fileName;
}
public string ResolveParameterValue(string directiveId, string processorName, string parameterName)
{
if (directiveId == null)
{
throw new ArgumentNullException("the directiveId cannot be null");
}
if (processorName == null)
{
throw new ArgumentNullException("the processorName cannot be null");
}
if (parameterName == null)
{
throw new ArgumentNullException("the parameterName cannot be null");
}
return String.Empty;
}
public void SetFileExtension(string extension)
{
FileExtension = extension;
}
public void SetOutputEncoding(Encoding encoding, bool fromOutputDirective)
{
FileEncoding = encoding;
}
public void LogErrors(CompilerErrorCollection errors)
{
Errors = errors;
}
public AppDomain ProvideTemplatingAppDomain(string content)
{
return AppDomain.CreateDomain("Generation App Domain");
}
}
在Main函数中
var templateFileName = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(Directory.GetCurrentDirectory())), "Template1.tt");
var host = new TextTemplatingEngineHost();
host.TemplateFileValue = templateFileName;
var template = new Template1();
template.Host = host;
var output = template.TransformText();
答案 0 :(得分:0)
您可以轻松地将输出写入特定文件,并防止模板使用几行代码将输出写入子节点。
将以下代码添加到模板的底部,或者在编写多个文件时在迭代结束时添加
。<#
SaveFile(entitiesFolder, entity.Name, this.GenerationEnvironment.ToString());
this.GenerationEnvironment.Remove(0, this.GenerationEnvironment.Length); //Removes the output
#>
SaveFile方法只是一个写入特定文件夹或路径的streamWriter。
public void SaveFile(string folder, string fileName, string content)
{
using (FileStream fs = new FileStream(Path.Combine(folder, fileName.Trim() + ".cs"), FileMode.Create))
{
using (StreamWriter str = new StreamWriter(fs))
{
str.WriteLine(content);
str.Flush();
}
}
}
我尝试了这个here。在此之前,我还尝试了该管理器文件。