2012-05-09 14 views
11

Cuando llama al RazorEngine.Razor.Compile(), ¿dónde se almacena la plantilla compilada?¿Cómo se almacenan en caché las plantillas en RazorEngine?

¿Está disponible después de reiniciar los programas? Si hay una escasez de memoria, ¿será objeto de dumping?

Estoy usando RazorEngine en un proyecto ASP.NET (MVC). ¿Las plantillas precompiladas estarán disponibles después de que se reinicie la aplicación?

¿Tendría más sentido para mí almacenarlos en el HttpContext.Cache? Si lo hiciera, ¿tendría más sentido utilizar una función diferente (distinta de Compile) que omita la caché interna? ¿Hay alguna forma de ejecutar un ITemplate y solo pasarle un modelo?

¿RazorEngine.Razor.Parse() hace algún almacenamiento en caché? ¿O es la plantilla recompilada cada vez?

Respuesta

16

Actualmente, después de que RazorEngine compila las plantillas, se cargan en la memoria. Estos ensambles persisten solo en la memoria y no continúan más allá de la duración de la aplicación.

Estoy considerando agregar soporte para compilar estos ensamblajes para los archivos, pero esa será una versión futura.

Si llama Razor.Parse y pasar el nombre de la plantilla, se intentará

  1. Compruebe el caché de ensamblados en memoria de un ensamblado con el mismo nombre.
  2. La memoria caché no válida del contenido de la plantilla ha cambiado.
  3. Guarda en caché la plantilla recién compilada.
+0

Muchas gracias por responder mi pregunta. No sé por qué nunca vi esto. Entonces, si y solo si paso un nombre a Razor.Parse y la plantilla es idéntica a la vez anterior llamé a Razor.Parse con el mismo nombre. ¿Entonces usará el ensamblado en caché en lugar de crear uno nuevo? – Rabbi

+0

@Rabbi Sí, así es como funciona. Al pasar un nombre de la plantilla, tomamos el código hash del contenido de la plantilla y lo almacenamos en la memoria caché junto con el tipo compilado dinámicamente. La próxima vez que lo llame, si el código hash de la cadena de la plantilla no ha cambiado, podemos instanciar libremente el tipo de plantilla y ejecutarlo. De lo contrario, invalidamos el tipo existente en la caché y volvemos a compilar la base en el nuevo contenido de la plantilla. –

+3

FYI, así no es como funciona en el RazorEngine actual. Profilling mostró Razor.Parse causando retrasos de 2 segundos en cada llamada web. Desactivándolo con Razor.GetTemplate(); Razor.Run(); correctamente desencadenado el almacenamiento en caché para nosotros. – KallDrexx

6

Tengo que esto funcione con RazorEngine 3.4.1.0, instalado a finales de enero de 2014.

La clave es llamar a la cara Razor.Compile(content, name) para poner la plantilla en caché, a continuación, llamar a la Razor.Run(name, model) barato para ejecutar la plantilla.

Recuerde que el contenido de la plantilla de lectura puede ser costoso, por ejemplo, que implica una lectura del disco, por lo que mi solución solo obtiene el contenido de la plantilla una vez. Esto podría ser demasiado almacenando en caché, ¡así que cuidado!

Aquí está el método RenderPartial que uso dentro de una subclase personalizada TemplateBase<T>. Se ejecuta muy rápido para múltiples llamadas a la misma plantilla.

public abstract class SqlTemplate<T>: TemplateBase<T> 
{ 
    public string RenderPartial(string templateName, object model = null) 
    { 
     // loading a template might be expensive, so be careful to cache content 
     if (Razor.Resolve(templateName) == null) 
     { 
      // we've never seen this template before, so compile it and stick it in cache. 
      var templateContent = GetTemplateContent(templateName); 
      Razor.Compile(templateContent, templateName); 
     } 

     // by now, we know we've got a the template cached and ready to run; this is fast 
     var renderedContent = Razor.Run(templateName, model); 
     return renderedContent; 
    } 

    private string GetTemplateContent(string templateName) 
    { 
     ... your implementation here 
    } 
} 

también hay que decir la maquinilla de afeitar para usar esta base de clase (SqlTempalte<T>) que se puede hacer como esto, llamando RazorEngineConfigurator.Configure();

public static class RazorEngineConfigurator 
{ 
    private static bool configured = false; 

    public static void Configure() 
    { 
     if (configured) 
     { 
      return; 
     } 

     var templateConfig = new TemplateServiceConfiguration 
     { 
      BaseTemplateType = typeof(SqlTemplate<>), 
      EncodedStringFactory = new RazorEngine.Text.RawStringFactory() 
     }; 

     RazorEngine.Razor.SetTemplateService(new TemplateService(templateConfig)); 

     configured = true; 
    } 
} 

No podría haber hecho sin this SO answer - por qué no dar que uno un up-voto, también? :)


Editar - Si usted necesita para llevar a cabo el almacenamiento en caché de una manera más granular, tendrá que utilizar un enfoque diferente utilizando RazorEngineTemplateService y ITemplateResolver.

Aquí hay un fragmento de código de inicio;

public static RazorEngineTemplateService CreateService(ITemplateResolver resolver, ICollection<string> namespaces) 
    { 
     Check.IsNotNull(resolver, "resolver"); 
     var config = new TemplateServiceConfiguration(); 
     config.BaseTemplateType = typeof(PlainTextTemplate<>); 
     config.EncodedStringFactory = new RazorEngine.Text.RawStringFactory(); 
     config.Resolver = resolver; 
     config.Namespaces = new HashSet<string>(namespaces); 

     var service = new RazorEngineTemplateService(config); 
     return service; 
    } 

ITemplateResolver convierte nombres de plantilla en contenido de la plantilla, por lo que puede poner en práctica, por ejemplo, un CachedFileTemplateResolver que carga contenido almacenado en caché de disco.

+0

¿Cómo puedo invalidar la caché sin reiniciar la aplicación? –

+1

Esta solución no lo hará por usted, me temo. Tuve que crear mi propio pequeño sistema para esto que utiliza la clase RazorEngine.Templating.ITemplateResolver para obtener el contenido de la plantilla. He agregado un código de inicio al final de mi respuesta en caso de que esto te ayude en el camino correcto. –

+0

¿Básicamente necesita colocar filewatchers en las plantillas en el disco para invalidar el caché y volver a compilarlo sobre la marcha? ¿Ya hay algo incorporado, o tengo que hacer esto yo mismo? – crush

Cuestiones relacionadas