2011-05-31 19 views
5

Tengo un objeto u1 de clase User. El usuario tiene un atributo name. ¿Cómo puedo pasar el u1 a una plantilla T4? Estoy tratando de hacer algo muy simple: la escriturapase un objeto a la plantilla T4

User u1 = new User("John"); 


Plantilla:

Hello <# u1.Name #> 

Respuesta

2

¿Quieres utilizarlo en su plantilla? Luego debe agregar una referencia al ensamblaje que contiene el tipo. No puedes simplemente pasar la referencia existente al motor T4 a menos que lo alojes tú mismo de una manera muy poco ortodoxa (nunca he visto a nadie que intente hacer esto). E incluso si llegaras tan lejos e hicieras eso, ¿cómo lo manejarías? ¿De dónde se supone que proviene esta referencia?

Usar el tipo de una plantilla T4 es tan fácil como agregar la referencia o copiarla/pegarla en el código de clase <#+ /*stuff goes here*/ #>.

+0

entiendo algo de lo que ha dicho, pero podría por favor, profundizar en esto: 'No se puede simplemente pasar de referencia existente en el motor T4 a menos que anfitrión usted mismo'? Además, solo quiero que lo sepa, tanto el archivo .tt como la clase de usuario forman parte de la misma solución – brainydexter

+1

Right. Bueno, no hay forma de entregar la referencia. La plantilla T4 en realidad se ejecuta en su propio dominio. Por varias razones. Si aloja el procesamiento T4, debería poder pasar una referencia al procesamiento, pero eso no es algo que haya visto antes. Lo mejor que puede hacer es referenciar un conjunto con las cosas que desea utilizar o agregar, como parte del código auxiliar de clase T4. Oleg Sych bloguea sobre T4, busca detalles sobre cómo hacerlo http://www.olegsych.com/2008/02/t4-assembly-directive/ –

1

Las plantillas T4 procesan en un solo paso, por lo que la plantilla necesita para obtener todo lo que necesita durante su ejecución allí para que realmente no "Pase" nada en ellas. Dado que la Plantilla es texto, generalmente solo tendré algunos parámetros que el desarrollador puede establecer en la parte superior del archivo. Si necesita la entrada del usuario, puede tener una ventana emergente, pero el hombre que suena molesto al generar el código.

Otra solución es utilizar una plantilla personalizada que utiliza la sustitución de plantilla en su plantilla t4 similar a cómo funcionan muchas de las plantillas instaladas.

+0

Como puedes ver, estoy empezando y mucho en la oscuridad. Pero, finalmente, lo que me gustaría hacer es crear un objeto compilado de la plantilla con referencias a un objeto de tipo usuario. Cuando la plantilla finalmente se 'ejecuta', usaría las propiedades del objeto para generar el texto. – brainydexter

0

Hey - es necesario establecer los valores, etc dentro de la secuencia de comandos T4, por lo que la inicialización User debe ocurrir dentro de la etiqueta <# #>, lo que convertiría que ejemplo en algo similar a

 <# User u1 = new User() { .Name = "John" } #> 
    Hello <# u1.Name #> 

Como se mencionó anteriormente es posible que también necesita importar espacios de nombres He utilizado las declaraciones a continuación en el inicio de un TT-archivo para obtener acceso a System.Data:

 <#@ import namespace="System.Data" #> 
    <#@ import namespace="System.Data.SqlClient" #> 
    <#@ assembly name="System.Data" #> 
1

Suponiendo que desea tener el código de alguna aplicación o herramienta que finalmente se ejecuta la plantilla, a continuación, utilizando el tiempo de ejecución (preprocesado) las plantillas con propiedades personalizadas definidas en un bloque de función de clase < # + #> o la directiva < # @ parámetro #> debería darle lo que desea.

Tener un vistazo a los documentos aquí: http://msdn.microsoft.com/en-us/library/gg586944.aspx

+0

Gracias por la respuesta. Decidimos no utilizar T4, ya que nos limitaba a usar el entorno host VS o invocar a un ejecutivo externo para el motor T4. La escala era nuestra principal preocupación e invocar al ejecutivo externo por llamada, es una operación que no podíamos afrontar. Por favor, avíseme si hay una solución a esto, ya que realmente me gustó el poder de T4 y encaja perfectamente con lo que estamos haciendo, pero nos está limitando en ese contexto. – brainydexter

+0

Los tempaltes preprocesados ​​no requieren host VS. Si el texto de su plantilla está arreglado en el momento de la compilación, deberían hacer lo que necesita. – GarethJ

3

Hicimos algo similar a esto. Nuestra solución tiene los siguientes elementos:

  • host personalizado
  • personalizado clase base de la plantilla ("hereda" la propiedad de directiva de plantilla) Plantillas
  • host específico (propiedad "hostspecific" de la directiva de plantilla)

El host personalizado se agrega por el objeto que la galería de símbolos quiere invocar en los métodos.

interface ICallbackInterface 
{ 
    void CallbackFxn(); 
} 

[Serializable] 
public class MyCustomHost : ITextTemplatingEngineHost, ITextTemplatingSessionHost, IStencilFileRecordManagement 
{ 

    private ICallbackInterface callback = null; 
    public MyCustomHost(ICallbackInterface cb) 
    { 
     callback = cb; 
    } 

    public void CallbackFxn() 
    { 
     callback.CallbackFxn(); 
    } 
} 

public abstract class MyTemplateBase : TextTransformation 
{ 
    public virtual MyCustomHost CustomHost 
    { 
     get 
     { 
      dynamic metame = this; 
      MyCustomHost rval = null; 
      try 
      { 
       /// <summary> 
       /// The "Host" property will be added to the generated class by the T4 environment whenever a 
       /// "hostspecific" template is processed. 
       /// </summary> 
       rval = metame.Host as MyCustomHost; 
      } 
      catch (RuntimeBinderException e) 
      { 
       logger.ErrorException(
        "Received the following exception while processing a stencil template", e); 

      } 
      return rval; 
     } 
    } 
} 

Ahora, en alguna de nuestras plantillas, podemos invocar métodos en el objeto que realmente se inició el tratamiento mediante la propiedad de host personalizado, por ejemplo:

<# CustomHost.CallbackFxn(); #> 

Además, no utilizamos T4 en VS o usando un archivo ejecutable por separado: enlazamos con los ensamblajes Microsoft.VisualStudio.TextTemplating.10.0 y Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.

EDITAR

Estamos utilizando plantillas T4 permiten a los usuarios definir sus propios plugins para su uso en un paso en particular en nuestro flujo de trabajo producto. Por lo que las plantillas de usuario se cargan en nuestro sistema, y ​​se procesan de esta manera:

using Microsoft.VisualStudio.TextTemplating; 

class UserPluginWorkflowComponent : ICallbackInterface 
{ 
    public void CallbackFxn() 
    { 
     // invoked by user plugin 
    } 

    public void ExecuteUserPlugin() 
    { 
     MyCustomHost host = new MyCustomHost(this); 
     host.TemplateFileValue = "UserPluginTemplateFilename"; 
     Engine engine = new Engine(); 
     string pluginResult = engine.ProcessTemplate(
      userPluginTemplateFileContents, 
      host);    
     if (!host.Errors.HasErrors) 
     { 
      // use pluginResult in some meaningful way 
     } 
    } 
} 
+0

¿Podría exponer un poco? Mostrar cómo un objeto "inicia el procesamiento" –

Cuestiones relacionadas