2010-02-21 54 views
20

Estamos construyendo una aplicación interna que necesita generar archivos HTML para cargar en listados de eBay. Estamos buscando utilizar un motor de plantillas para generar los archivos HTML basados ​​en bases de datos y campos estáticos que hemos predefinido. La plantilla también necesita tener capacidades lógicas (if-then, foreach, etc.).Crear plantillas T4 en tiempo de ejecución (tiempo de compilación)?

Hemos visto T4 y se ve perfecto, pero no vemos nada acerca de si tiene las capacidades para ser utilizado en tiempo de ejecución, para que un usuario pueda crear la plantilla T4, y luego la aplicación puede "compilar" "y generar el archivo HTML final. ¿Es esto posible y cómo?

Si no, ¿hay otros marcos que deberíamos considerar que tengan todas estas capacidades?

Respuesta

16

Tengo un conjunto similar de clases que utilizo para esto, incorporando la generación de texto con plantilla en el software.

Básicamente, funciona como ASP antiguo, rodea el código C# en los bloques <%...%>, y puede emitir resultados usando <%= expression %>.

Puede pasar un solo objeto al código de plantilla, que por supuesto puede ser del tipo de objeto que desee, o simplemente una matriz de parámetros. También puede hacer referencia a sus propios ensamblajes si desea ejecutar código personalizado.

Así es como emisor de una clase se vería:

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

Puede, por bucle curso a través de las cosas:

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

y poner el código en si-bloques etc.

la biblioteca de clases se libera en CodePlex aquí:

, así como en NuGet.

El proyecto viene con ejemplos, descargue la fuente o browse it online.

Para responder a las preguntas por correo electrónico también aquí, para que otros puedan ver:

  1. Todos los tipos de código C# que caben en una llamada al método puede ser compilado en la plantilla. Ejecuta el código normal de C# 3.5, con todo lo que eso significa, no hay límites artificiales. Lo único que debe saber es que cualquier código de if, while, for, foreach, etc. que contenga código de plantilla para emitir debe usar llaves, no puede hacer un bloque de tipo if-then de una sola línea. Vea a continuación la limitación de la llamada al método.
  2. El parámetro data corresponde a lo que se haya pasado como el parámetro para el método .Generate(x) desde su aplicación, y es del mismo tipo. Si transfiere un objeto que ha definido en sus propias bibliotecas de clase, debe agregar una referencia al código de la plantilla para acceder correctamente.(<%@ reference your.class.library.dll %>)
  3. Si reutiliza la plantilla compilada, en esencia solo será una llamada de método a una clase, no se realiza una sobrecarga adicional en la llamada real al .Generate(). Si no llama al .Compile() usted mismo, la primera llamada al .Generate() se encargará de ello. También tenga en cuenta que el código se ejecuta en un dominio de aplicación separado, por lo que hay una ligera sobrecarga de clasificación relacionada con la copia del parámetro y el resultado de ida y vuelta. El código, sin embargo, se ejecuta a la velocidad normal del código .NET JITted.

Ejemplo de bloque if:

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

No hay límites artificiales en el formato del código o bien, escoger el estilo que más le convenga:

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

Sólo tenga en cuenta que todas libres las partes del código de la plantilla prácticamente se enviarán tal como están, lo que significa que también se mostrarán las siguientes pestañas y los siguientes bloques %>.

Hay un límite, todo el código que escriba debe caber dentro de una sola llamada a método.

Déjame explicarte.

La forma en que funciona el motor de plantillas es que produce un archivo .cs y la alimenta al compilador de C#, este archivo de Cs roughyly se parece a esto:

using directives 

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

Esto significa que no se pueden definir nuevas clases , nuevos métodos, campos de nivel de clase, etc.

Sin embargo, puede usar delegados anónimos para crear funciones internamente. Por ejemplo, si desea una forma uniforme de las fechas de formato:

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

A continuación, puede utilizar que en el resto del código de la plantilla:

<%= date2str(DateTime.Now) %> 

Único requisito que tengo es que usted don' Cargue los archivos en la web y afirme que escribió el código. Aparte de eso, puede hacer lo que quiera con él.

Editar 23.04.2011: Vínculos fijos al proyecto CodePlex.

+0

Wooow O.o Estoy descargando esto ahora mismo y le haré saber cómo funciona. Si hace todo lo que dices, ¡serás un absoluto salvavidas! – Amberite

+0

Editó la respuesta ahora, como dijo en el correo electrónico, la variable "Datos" no existe, porque se llama "datos". Es un parámetro de método, de ahí la "d" minúscula. –

+0

"La forma en que funciona el motor de plantilla es que produce un archivo .cs y lo alimenta al compilador de C#": ¿No significaría también que la máquina que ejecuta esto necesita VisStudio o al menos algo más instalado? ¿O hay alguna forma de que llame programáticamente al compilador de C#? No creía que el compilador se enviara con el tiempo de ejecución de .NET ... Aunque como IIS puede compilar ASP.NET sobre la marcha, creo que debe estar en alguna parte ... – CodingWithSpike

3

Las plantillas T4 se pueden compilar con la herramienta de línea de comandos TextTransform.exe. Usted podría hacer que su aplicación cree un archivo .tt, luego llame a TextTransform.exe para generar el resultado.

+0

¿No es necesario instalar Visual Studio en la máquina del usuario con esta solución? Esto es una limitación para nosotros. – Amberite

+0

Mono tiene una implementación de transformación de texto bastante capaz. Me gustaría echarle un vistazo a eso si las dependencias son un problema. –

+2

Sí, por ahora, es una dependencia de Visual Studio. Esto cambiará con VS2010/.NET 4 y las llamadas plantillas precompiladas T4. Consulte aquí para obtener información: http://www.olegsych.com/2009/09/t4-preprocessed-text-templates/ –

6

El ensamblado que implementa la transformación de texto T4 es Microsoft.VisualStudio.TextTemplating.dll, que se envía con Visual Studio.

Si desea comenzar desde los primeros principios, debe implementar Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost y pasar su implementación como argumento a Microsoft.VisualStudio.TextTemplating.Engine.ProcessTemplate(), que realizará la transformación.

Esto le da más flexibilidad que llamar a TextTransform.exe.

Sin embargo, si su código es un producto de envío, no está claro cuál es la licencia de este conjunto, y si tiene los derechos para redistribuirlo con su aplicación.

La redistribución de este conjunto evitaría la necesidad de instalar Visual Studio.

+0

Lamentablemente, esto no satisface nuestras necesidades debido al problema de la licencia, ya que este producto se enviará a los usuarios finales. Gracias de todos modos :) – Amberite

+1

También hay una implementación de código abierto por el proyecto Mono. http://anonsvn.mono-project.com/viewvc/trunk/monodevelop/main/src/addins/TextTemplating/ –

3

Es completamente posible utilizar T4 en tiempo de ejecución.

Microsoft realmente no admite este escenario de ninguna manera razonable en .NET 3.5. Parece que .NET 4.0 tendrá mejor soporte de Microsoft.

Mono proporciona algo de soporte para este escenario en .NET 3.5.

He probado este concepto con éxito con .NET 3.5 con la ayuda de la implementación de Mono T4, pero una solución estándar para este problema para .NET 3.5 requeriría un esfuerzo mucho mayor de lo que he invertido hasta ahora.

Puede encontrar la aplicación Mono T4 aquí:

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

he documentado algunos de los problemas que me encontré tratando de ejecutar las plantillas T4 de código .NET aquí:

Options for running T4 templates from .NET code

14

Si puede usar Visual Studio 2010 para la creación y edición de plantillas, puede usar plantillas precompiladas, que fueron diseñadas exactamente para este escenario y son la opción compatible de Microsoft.

Diseñe la plantilla en Visual Studio, precompílela e implemente un ensamblado que no tenga dependencias en Visual Studio junto con su aplicación.

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

0

Un error que hice es añadí un archivo "plantilla de texto". Para generar texto en runtime, elija la "Plantilla de texto preprocesado". Si originalmente eligió "Plantilla de texto", es un cambio sencillo configurar la herramienta personalizada en "TextTemplatingFilePreprocessor" en las propiedades del archivo en VS.

Cuestiones relacionadas