使用与模板位于同一项目中的T4模板中的类型

我正在研究我的第一个T4代码生成工具,为我的项目添加一些存储过程帮助程序代码。 我已经创建了自定义类型(例如StoredProcedureStoredProcedureParameter来帮助我生成代码,并在我的代码中包含了程序集和命名空间引用:

     

这允许我在我的T4模板代码中使用我的自定义类型。 但是,因为我的自定义类型与T4模板代码存在于同一个项目中,所以在运行模板代码而不重新启动Visual Studio时,我无法重新编译项目。 这不是很有趣。

我读了一篇很棒的文章 ,通过使用T4工具箱解决了这个问题,但是它没有用。 我正在实现VolatileAssembly指令错误或者T4工具箱根本没有安装。 我不确定工具箱是否正确安装(我在Win XP上使用VS 2010)。

有什么方法可以解决这个问题?

您需要删除以前的assembly引用, 然后添加VolatileAssembly引用。 如果不首先删除常规assembly引用,则会在添加VolatileAssembly引用时收到已添加的错误。

 <#@ template debug="false" hostspecific="false" language="VB" #> <#@ output extension=".generated.vb" #> 

<#@ assembly name="$(TargetPath)" #>

 <#@ VolatileAssembly processor="T4Toolbox.VolatileAssemblyProcessor" name="$(TargetPath)" #> <#@ import namespace="StoredProcCodeGenerator" #> 

现在,您可以继续构建项目,并在T4模板中使用该项目中定义的类型。

希望这是有用的,它显示了使用volatileAssembly的一个用例,我没有任何运气让这个t4模板工作,但我认为它可能会有所帮助:

 //  // Last generated <#= DateTime.Now #> <#@ template language="C#" hostspecific="true"#> <#@ assembly name="System" #> <#@ VolatileAssembly processor="T4Toolbox.VolatileAssemblyProcessor" name="bin\debug\FrameworkWpf.dll" #> <#@ VolatileAssembly processor="T4Toolbox.VolatileAssemblyProcessor" name="bin\debug\FrameworkTestToolkit.dll" #> <#@ VolatileAssembly processor="T4Toolbox.VolatileAssemblyProcessor" name="bin\debug\WpfAppTemplate.exe" #> <#@ output extension=".cs" #> <#@ import namespace="System" #> <#@ import namespace="FrameworkTestToolkit" #> namespace WpfAppTemplateTest { using System; using System.Reflection; <# // Add new types into the below array: Type[] types = new Type[] { typeof(FrameworkWpf.SafeEvent), typeof(FrameworkWpf.Mvvm.ControllerBase), typeof(FrameworkTestToolkit.PrivateAccessorGeneratorTestClass), typeof(WpfAppTemplate.PostController), typeof(WpfAppTemplate.ShellController), }; // Do not modify this code foreach (Type type in types) { PrivateAccessorGenerator builder = new PrivateAccessorGenerator(type, WriteLine, Error, Warning); builder.Generate(); } #> } 

来自http://blog.rees.biz/Home/unit-testing-and-private-accessors2

您还可以使用EnvDte遍历代码:

  <#@ template language="C#" hostspecific="True" debug="True" #> <#@ output extension="cs" #> <#@ assembly name="System.Core" #> <#@ assembly name="System.Xml" #> <#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0" #> <#@ assembly name="EnvDTE" #> <#@ assembly name="EnvDTE80" #> <#@ assembly name="VSLangProj" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Text.RegularExpressions" #> <#@ import namespace="System.Xml" #> <#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #> <#@ import namespace="EnvDTE" #> <#@ import namespace="EnvDTE80" #> <#@ import namespace="Microsoft.VisualStudio.TextTemplating" #><# var serviceProvider = Host as IServiceProvider; if (serviceProvider != null) { Dte = serviceProvider.GetService(typeof(SDTE)) as DTE; } // Fail if we couldn't get the DTE. This can happen when trying to run in TextTransform.exe if (Dte == null) { throw new Exception("T4Generator can only execute through the Visual Studio host"); } Project = GetProjectContainingT4File(Dte); if (Project == null) { Error("Could not find the VS Project containing the T4 file."); return"XX"; } AppRoot = Path.GetDirectoryName(Project.FullName) + '\\'; RootNamespace = Project.Properties.Item("RootNamespace").Value.ToString(); Console.WriteLine("Starting processing"); ProcessFileCodeModel(Project); #> 

我在http://imaginarydevelopment.blogspot.com/2010/11/static-reflection-or-t4-with-envdte.html上发布了更多代码作为基础。