2010-08-04 15 views
20

Je travaille sur mon premier outil de génération de code T4 pour ajouter du code auxiliaire de procédure stockée à mon projet. J'ai créé des types personnalisés (par exemple StoredProcedure et StoredProcedureParameter pour aider à ma génération de code et inclus l'assemblage et de références espace de noms dans mon code:Utilisation de types dans un modèle T4 qui existent dans le même projet que le modèle

<#@ template debug="false" hostspecific="false" language="VB" #> 
<#@ output extension=".generated.vb" #> 
<#@ assembly name="$(TargetPath)" #> 
<#@ import namespace="StoredProcCodeGenerator" #> 

Cela me permet d'utiliser mes types personnalisés dans mon code de modèle T4. Toutefois, étant donné que mes types personnalisés existent dans le même projet que le code du modèle T4, je ne peux pas recompiler mon projet une fois que j'ai exécuté le code du modèle sans redémarrer Visual Studio. great article qui résout ce problème en utilisant la boîte à outils T4, mais cela ne fonctionne pas.Si j'implémente la directive VolatileAssembly ou la boîte à outils T4 mply ne s'est pas installé. Je ne suis pas sûr que la boîte à outils a été installée correctement (j'utilise VS 2010 sur Win XP).

De quelles façons pourrais-je résoudre ce problème?

+0

Je ne comprends pas. Dans VS2010, j'utilise des modèles T4 tout le temps, y compris en utilisant des types qui sont dans le même projet que le modèle, et cela fonctionne très bien et réexécute le modèle chaque fois que j'enregistre - comme je m'y attendais. –

+0

@Kirk Je ne me suis pas rendu compte que je devais supprimer '<# ​​@ assembly name =" $ (TargetPath) "#>' avant d'ajouter '<# ​​@ VolatileAssembly ...'. J'ai ajouté une réponse pour l'expliquer. –

+1

quelqu'un peut-il éditer le titre pour dire le modèle au lieu de tempérer près du début? – Maslow

Répondre

10

Vous devez supprimer la référence assembly précédente et puis ajouter la référence VolatileAssembly. Si vous ne supprimez pas la référence assembly d'abord, vous obtiendrez une erreur qui a déjà été ajoutée lorsque vous ajoutez la référence VolatileAssembly.

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

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

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

Maintenant, vous pouvez continuer à construire votre projet et utiliser des types définis dans ce projet dans vos modèles T4.

+0

Que se passe-t-il quand vous n'avez ni l'un ni l'autre? (Je n'ai ni "assembly" ni "VolatileAssembly" et les classes du projet qui contient le fichier .tt sont toujours accessibles pour moi.) –

+0

@Kirk C'est intéressant. Si je n'inclue pas de référence d'assembly, j'obtiens une erreur indiquant qu'il ne trouve pas mes types personnalisés. Par exemple, j'ai un type 'StoreProcedure' que je consomme dans mon fichier .tt. Si je ne référence pas mon assembly, il ne pourra pas trouver le type 'StoredProcedure'. –

+2

Kirk, utilisez-vous VS2008 peut-être? En 2008, nous avons également introduit les types locaux dans les références du projet en tant que recherches sur les standards. Nous avons supprimé cela en 2010 pour que votre monde T4 soit isolé de ce que vous étiez en train de construire. Nous l'avons fait pour soutenir le ciblage des projets .Net 2.0 ou 3.5 tout en utilisant .Net 4.0 dans les modèles. – GarethJ

1

Espérons que cela est utile, il montre un cas d'utilisation de consommer la volatileAssembly, je ne suis pas avoir de chance d'obtenir ce modèle t4 de travailler du tout, mais je pense qu'il peut être utile:

// <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(); 
} 
#> 
} 

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

1

Vous pouvez également parcourir le code en utilisant 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); 
    #> 

J'ai posté encore plus code en utilisant comme base à http://imaginarydevelopment.blogspot.com/2010/11/static-reflection-or-t4-with-envdte.html

+0

qu'est-ce que 'EnvDTE'? –

+0

@Ben - édité la réponse pour inclure des liens de ressources – Maslow

+0

Mais cela a juste RootNamespace comme un littéral de chaîne. Comment l'utilisez-vous comme directive? – William