Git Product home page Git Product logo

Comments (12)

Antaris avatar Antaris commented on July 30, 2024

Hi,

Caching is scoped per instance of a template service, which means that if you are spinning up new instances each time then you'll lose your cached templates. I'm investigating whether to make cached templates global, might add in a configuration option to enable this.

As for recommendations, you'll probably simply want to use the Razor static type, which maintains a singleton instance of a template service for you. This singleton instance can be replaced with your own preconfigured instance of an ITemplateService. To minimise the number of recompilations for your web-app, this is the route I would take.

Pre-compilation is still supported, but the Compile method hasn't been implemented. Essentially making a call to GetTemplate will achieve the same thing, but I will be adding the Compile (and Run) method(s) back in for backwards compatibility.

from razorengine.

Madd0g avatar Madd0g commented on July 30, 2024

Thanks for the reply.

Is there a way to use the ITemplate that is returned from GetTemplate and CreateTemplate to be filled with a model? Like if I want to keep a reference to the template I get from CreateTemplate and use it directly.

I see Execute and Run, but one doesn't accept parameters and the other accepts ExecuteContext and I haven't seen examples of how it can be used.

from razorengine.

Antaris avatar Antaris commented on July 30, 2024

Hi,

ExecuteContext is an implementation detail, you can easily spin up a new instance of it: new ExecuteContext(). Normally the framework itself will handle this, as it is used to track sections and layouts (stacking) while the template is executing. We can't easily return an instance of ITemplate<T> because we can't return a generic type when the model is anonymous or dynamic. This means we only return an instance of ITemplate.

If you know your model type, you can easily cast back to the base template type, e.g.:

var tmp = (TemplateBase<MyModel>)instance;
tmp.Model = model;

The Execute and Run methods have specific purposes. The Execute method is what is generated by the Razor parser, it is void which means we can't return anything, and it essentially just builds the merged content of the result and sets it into an internal writer.

The Run method simply executes the Execute method, and returns the string result.

When I get round to implementing Run on the ITemplateService, I'll take care of the ExecuteContext instantiation for you

from razorengine.

Madd0g avatar Madd0g commented on July 30, 2024

var tmp = (TemplateBase<MyModel>)instance; tmp.Model = model;

Ah... very nice, this should definitely be in the documentation.
If there was a helper to do this work - it would feel a lot more natural.

from razorengine.

Antaris avatar Antaris commented on July 30, 2024

LOL, as with the code, the documentation is work-in-progress ;-).

I think the Run method will essentially suit your needs. 9/10 times you'll only ever be using the template service operations (Parse, ParseMany, etc.), so interacting with the template instances themselves should be a pretty sporadic use case.

Watch this space for updates :-)

from razorengine.

Antaris avatar Antaris commented on July 30, 2024

The beta release that dropped last night (v3.0.0beta) includes support for the Compile and Run helper methods. These are defined in ITemplateService, and also made part of the Razor static type.

Let me know if you have any issues.

from razorengine.

Madd0g avatar Madd0g commented on July 30, 2024

I just want to make sure, if I keep a reference to ITemplate - I don't have to worry about naming the template and such?

This is my usage, it's a bit weird, because of the double cast when parsing the template, but it works - but does it correctly cache?

Creation:

var type = Type.GetType(sModelType);
var typeInstance = (IMyInterface)Activator.CreateInstance(type);
template.CompiledTemplate = Service.CreateTemplate(sTemplate, typeInstance);

Usage:

var concreteTemplate = (TemplateBase<IMyInterface>) template.CompiledTemplate;
concreteTemplate.Model = model;    
var result = ((ITemplate) concreteTemplate).Run(new ExecuteContext());

If I keep a reference to template.CompiledTemplate and run it like this - will caching work?

Thank you!

from razorengine.

Antaris avatar Antaris commented on July 30, 2024

Well, the type itself will not be cached, but you'll have an instance of ITemplate that you hold onto anyway. It's important that you always use Run instead of Execute though, as Run will create our buffer that content will be written into, which then returns the result.

This might get a little more complicated when you want to use Layouts/Sections or Includes, because it will need to call back to the ITemplateService to resolve those templates.

from razorengine.

Madd0g avatar Madd0g commented on July 30, 2024

Thanks, as long as it's going to be possible, I don't mind adding extra code to support Layouts (I will have a reference to the template service whenever I use the stored ITemplate).

from razorengine.

Antaris avatar Antaris commented on July 30, 2024

The other thing to watch out for, is that ITemplate by itself is not threadsafe. You can't use the Run method concurrently, as it only has a single buffer to write to. You'll end up with mangled content if you do...

from razorengine.

Madd0g avatar Madd0g commented on July 30, 2024

that's not optimal - so my only option is to use the named templates?

that's a bit awkward, the choice is between creating and storing a guid for each and every thing I want to cache, I also thought of using glued names (model.id + model.categoryid) as a key - but I have a ienumerable member with it's own templates and it gets so much more complicated because they don't have ids. Not to mention that strings are horrible for maintenance.

I'm a bit disappointed, I can't see how to accomplish anything elegant with strings without writing a huge helper to abstract the strings away.

from razorengine.

Antaris avatar Antaris commented on July 30, 2024

I think what you need to do, is expose template activation instead. The ITemplateService supports the operation CreateTemplateType which returns the Type instance of your compiled type. You could store that, and perhaps if I make the protected method CreateTemplate<T>(Type type, T model) public, you could then call back to the TemplateService to activate the template, so essentially you create a new instance each time you want (thus bypassing any threading issue). Then perhaps if your code did something like:

public class ConcreteInstance
{
    public Type TemplateType { get; set; }
    pulibic TemplateService TemplateService { get; set; }

    public ITemplate CreateTemplate<T>(T model) 
    {
        return this.TemplateService.CreateTemplate(TemplateType, model);
    }
}

? I'd need to make an update to support that, but if that helps it can be done...

from razorengine.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.