2010-02-21 7 views
20

Nous construisons une application interne qui doit générer des fichiers HTML à télécharger dans les listes eBay. Nous cherchons à utiliser un moteur de template pour générer les fichiers HTML basés sur la base de données et les champs statiques que nous avons prédéfinis. Le modèle doit également avoir des capacités logiques (if-then, foreach, etc.). Nous avons regardé T4 et cela a l'air parfait, mais nous ne voyons pas s'il a les capacités à utiliser lors de l'exécution, pour qu'un utilisateur puisse créer le template T4, et ensuite l'application peut "compiler" "il et générer le fichier HTML final. Est-ce possible et comment?Création de modèles T4 lors de l'exécution (temps de construction)?

Si ce n'est pas le cas, y a-t-il d'autres cadres que nous devrions examiner qui ont toutes ces capacités?

Répondre

16

J'ai un ensemble similaire de classes que j'utilise pour cela, en intégrant la génération de texte modélisé dans le logiciel.

Fondamentalement, cela fonctionne comme ASP ancien, vous entourez le code C# dans <%...%> blocs, et vous pouvez émettre des résultats en utilisant <%= expression %>.

Vous pouvez transmettre un seul objet dans le code du modèle, ce qui peut bien sûr être n'importe quel type d'objet que vous aimez, ou simplement un tableau de paramètres. Vous pouvez également référencer vos propres assemblys si vous souhaitez exécuter du code personnalisé.

Voici comment émettre une classe regarderait:

<% 
var parameters = (string[])data; 
var namespaceName = parameters[0]; 
var className = parameters[1]; 
%> 
namespace <%= namespaceName %> 
{ 
    public class <%= className %> 
    { 
    } 
} 

Vous pouvez la boucle de cours à travers les choses:

<% foreach (var parameter in parameters) { %> 
<%= parameter %> 
<% } %> 

et mettre le code si-blocs, etc.

La bibliothèque de classe est publié sur CodePlex ici:

ainsi que sur NuGet.

Le projet est livré avec des exemples, télécharger la source ou browse it online.

Pour répondre aux questions par e-mail ici aussi, pour d'autres à voir:

  1. Tous les types de code C# qui entrent dans un appel de méthode peut être compilé dans le modèle. Il fonctionne avec du code C# 3.5 normal, avec tout ce que cela signifie, il n'y a pas de limites artificielles. Seules les choses à savoir est que tout code if, while, for, foreach, etc. qui contient du code de modèle à émettre doit utiliser des accolades, vous ne pouvez pas faire un bloc de type if-then sur une seule ligne. Voir ci-dessous pour la limitation de l'appel de méthode.
  2. Le paramètre data correspond à tout ce qui a été transmis en tant que paramètre à la méthode .Generate(x) à partir de votre application et est du même type. Si vous transmettez un objet que vous avez défini dans vos propres bibliothèques de classes, vous devez ajouter une référence au code du modèle afin de pouvoir y accéder correctement.(<%@ reference your.class.library.dll %>)
  3. Si vous réutilisez le modèle compilé, il s'agira essentiellement d'un appel de méthode à une classe, aucun surcoût supplémentaire n'est effectué sur l'appel réel à .Generate(). Si vous n'appelez pas .Compile() vous-même, le premier appel à .Generate() s'en occupera. Notez également que le code s'exécute dans un domaine d'application distinct, il y a donc une légère surcharge liée à la copie du paramètre et au résultat d'avant en arrière. Le code, cependant, s'exécute à la vitesse du code JITted .NET normal.

Exemple de si-bloc:

<% if (a == b) { %> 
This will only be output if a==b. 
<% } %> 

Il n'y a pas des limites artificielles sur le formatage du code soit, choisissez le style qui vous convient le mieux:

<% 
    if (a == b) 
    { 
%> 
This will only be output if a==b. 
<% 
    } 
%> 

noter seulement que tous les non les parties de code du modèle seront à peu près sorties telles quelles, ce qui signifie que les onglets et les blocs %> suivants seront également générés.

Il y a une limite, tout le code que vous écrivez doit tenir dans un seul appel de méthode.

Laissez-moi vous expliquer.

La façon dont fonctionne le moteur de modèle est qu'il produit un fichier .cs et nourrit au compilateur C#, ce .cs fichier ressemble roughyly comme ceci:

using directives 

namespace SomeNamespace 
{ 
    public class SomeClass 
    { 
     public string Render(object data) 
     { 
      ... all your code goes here 
     } 
    } 
} 

Cela signifie que vous ne pouvez pas définir de nouvelles classes , de nouvelles méthodes, des champs de niveau classe, etc.

Vous pouvez toutefois utiliser des délégués anonymes pour créer des fonctions en interne. Par exemple, si vous voulez un moyen uniforme de dates de mise en forme:

Func<DateTime, string> date2str = delegate(DateTime dt) 
{ 
    return dt.ToString("G"); 
}; 

alors vous pouvez simplement utiliser que dans le reste du code du modèle:

<%= date2str(DateTime.Now) %> 

Seulement condition que j'ai est que vous n » t télécharger les fichiers sur le web et prétendre que vous avez écrit le code, sauf que vous êtes libre de faire ce que vous voulez avec.

Édition 23.04.2011: Liens fixes au projet CodePlex.

+0

Wooow O.o Je télécharge ceci maintenant et je vous ferai savoir comment ça se passe. S'il fait tout ce que vous dites, vous serez un sauveur de vie absolue! – Amberite

+0

Edité la réponse maintenant, comme vous l'avez dit dans l'email, la variable "Data" n'existe pas, car elle s'appelle "data". C'est un paramètre de méthode, d'où le "d" minuscule. –

+0

"Le fonctionnement du moteur de gabarit est qu'il produit un fichier .cs et le transmet au compilateur C#": cela ne signifie-t-il pas que la machine qui exécute cela a besoin de VisStudio ou au moins quelque chose d'autre? Ou y a-t-il un moyen que vous appeliez par programmation le compilateur C#? Je ne pensais pas que le compilateur était livré avec le .net runtime ... Bien qu'IIS puisse compiler ASP.NET à la volée, je suppose qu'il doit être là quelque part ... – CodingWithSpike

3

Les modèles T4 peuvent être compilés avec l'outil de ligne de commande TextTransform.exe. Vous pouvez avoir votre application créer un fichier .tt, puis appelez TextTransform.exe pour générer la sortie.

+0

Visual Studio ne doit-il pas être installé sur la machine de l'utilisateur avec cette solution? Ceci est une limitation pour nous. – Amberite

+0

Mono a une implémentation de transformation de texte assez performante. J'y jetterai un coup d'oeil si les dépendances sont un problème. –

+2

Oui, pour l'instant, c'est une déférence sur Visual Studio. Cela va changer avec VS2010/.NET 4 et les modèles T4 précompilés. Voir ici pour info: http://www.olegsych.com/2009/09/t4-preprocessed-text-templates/ –

6

L'assembly qui implémente la transformation de texte T4 est Microsoft.VisualStudio.TextTemplating.dll, fourni avec Visual Studio.

Si vous voulez commencer à partir des premiers principes, vous devez implémenter Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost et passer votre implémentation en tant qu'argument à Microsoft.VisualStudio.TextTemplating.Engine.ProcessTemplate(), qui effectuera la transformation.

Cela vous donne plus de flexibilité que d'appeler TextTransform.exe.

Toutefois, si votre code est un produit d'expédition, il est difficile de savoir quelles sont les licences de cet assemblage et si vous avez le droit de le redistribuer avec votre application.

La redistribution de cet assembly éviterait l'installation de Visual Studio.

+0

Malheureusement, cela ne répond pas à nos besoins en raison du problème de licence, car ce produit sera expédié aux utilisateurs finaux. Merci quand même :) – Amberite

+1

Il existe également une implémentation open-source par le projet Mono. http://anonsvn.mono-project.com/viewvc/trunk/monodevelop/main/src/addins/TextTemplating/ –

3

Il est complètement possible d'utiliser T4 à l'exécution.

Microsoft ne prend pas réellement en charge ce scénario de manière raisonnable dans .NET 3.5. Il semble que .NET 4.0 aura un meilleur support de Microsoft.

Mono fournit un support pour ce scénario dans .NET 3.5.

J'ai testé avec succès ce concept avec .NET 3.5 avec l'aide de l'implémentation de Mono T4, mais une solution prête à l'emploi pour ce problème pour .NET 3.5 exigerait beaucoup plus d'efforts que j'ai investi jusqu'ici.

Vous pouvez trouver la mise en œuvre Mono T4 ici:

https://github.com/mono/monodevelop/tree/master/main/src/addins/TextTemplating

J'ai documenté quelques-unes des questions que j'ai rencontrés en essayant d'exécuter des modèles T4 à partir du code .NET ici:

Options for running T4 templates from .NET code

14

Si vous pouvez utiliser Visual Studio 2010 pour la création et la modification de modèles, vous pouvez utiliser des modèles précompilés, conçus pour exactement ce scénario et pris en charge par Microsoft.

Vous concevez le modèle dans Visual Studio, le précompilez et déployez un assembly qui ne dépend pas de Visual Studio avec votre application. fichier

http://www.olegsych.com/2009/09/t4-preprocessed-text-templates/

0

Une erreur que je fait est que j'ajouté un « modèle de texte ». Pour générer du texte à runtime, sélectionnez le "Modèle de texte prétraité" à la place. Si vous avez initialement choisi "Modèle de texte", il est facile de définir l'outil personnalisé sur "TextTemplatingFilePreprocessor" dans les propriétés du fichier dans VS.