Использование типов в шаблоне T4, которые существуют в том же проекте, что и шаблон - PullRequest
21 голосов
/ 04 августа 2010

Я работаю над своим первым инструментом генерации кода 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).

Какими способами я могу решить эту проблему?

Ответы [ 3 ]

10 голосов
/ 04 августа 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.

1 голос
/ 10 ноября 2010

Вы также можете пройти код, используя 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

1 голос
/ 10 ноября 2010

Надеюсь, это полезно, оно показывает случай использования 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

...