Использование типов в шаблоне T4, которые существуют в том же проекте, что и шаблон
Я работаю над своим первым инструментом генерации кода T4, чтобы добавить в мой проект некоторый код хранимой процедуры. Я создал настраиваемые типы (например, StoredProcedure
и StoredProcedureParameter
, чтобы помочь в генерации кода и включил ссылки на сборку и пространство имен в моем коде:
<#@ template debug="false" hostspecific="false" language="VB" #>
<#@ output extension=".generated.vb" #>
<#@ assembly name="$(TargetPath)" #>
<#@ import namespace="StoredProcCodeGenerator" #>
Это позволяет мне использовать мои пользовательские типы в моем коде шаблона T4. Однако, поскольку мои пользовательские типы существуют в том же проекте, что и код шаблона T4, я не могу перекомпилировать мой проект после запуска кода шаблона без перезапуска Visual Studio. Это не очень весело.
Я прочитал статью отличную статью, которая касается этой точной проблемы с помощью T4 Toolbox, но она не работает. Либо я реализую директиву VolatileAssembly
, либо панель инструментов T4 просто не установлена. Я не уверен, что набор инструментов установлен правильно (я использую VS 2010 в Win XP).
Какими способами я могу решить эту проблему?
Ответы
Ответ 1
Вам нужно удалить предыдущую ссылку 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.
Ответ 2
Надеюсь, это полезно, это показывает пример использования volatileAssembly, мне не удастся заставить этот шаблон t4 работать вообще, но я думаю, что это может быть полезно:
// <autogenerated/>
// 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
Ответ 3
Вы также можете пройти код, используя 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