Antaris / RazorEngine

Open source templating engine based on Microsoft's Razor parsing engine
http://antaris.github.io/RazorEngine
Other
2.14k stars 578 forks source link

CreateTemplateType + CreateTemplate alternatives after upgrade #441

Open mtdaniels opened 7 years ago

mtdaniels commented 7 years ago

I'm attempting to upgrade from pre-3.5 to 3.9 (I know, we're a bit behind). I'm looking for the upgrade path for ITemplateService.CreateTemplateType and ITemplateService.CreateTemplate. I do see Compile and RunCompile; however, we are currently leveraging the control allowed by compiling / instantiating / running as disparate actions.

As best I can tell, CreateTemplateType and CreateTemplate still exist in RazorEngineCore, but are inaccessible.

matthid commented 7 years ago

There are a lot of workarounds depending on what you are trying to achieve. Can you give sample code or describe you use case. Alternatively you can look into some old closed questions at the time of release. There always were better approaches which weren't as deeply coupled to the internal workings of RazorEngine.

Marking stuff like these as internal allows us to make breaking changes there or remove them entirely. The interface was really an implementation detail and shouldn't have been exposed.

mtdaniels commented 7 years ago

We create a tool which can be used to edit razor. We need to be able to try/catch compilation to show compilation exceptions. As long as IRazorEngineService.Compile still throws compilation exceptions, this should be fine.

CreateTemplate is used because we need to perform some initialization on the template instance prior to running it (it is composed using MEF, for instance). Run and RunCompile don't appear to allow any custom initialization on the template instance before running.

CreateTemplateType is used because we need the type to pass into CreateTemplate. Also, we do this as a means to use template types which are compiled in the assembly (not editable at runtime). We map some keys to a compiled type. The pre-compiled-template-map might be achievable using a custom ICachingProvider, though the ITemplateSource and CompilationData would be null (not sure if that would cause any issues).

matthid commented 7 years ago

So the only thing left is the custom initialization code? You might be able to do somthing similar with your own template base class...

mtdaniels commented 7 years ago

If I need external state for initialization (which is the case for DI), I don't think that is possible.

Something else I missed - we get the instance of the template a few different reasons:

  1. custom initialization / DI (mentioned before)
  2. sometimes the template is instantiated, information is retrieved (which is included in our own base class, and can be modified by the compiled razor), but the template instance is not actually run. Specifically, we use this as a means to include information about template-specific parameters.
  3. our template base class has more lifecycle-type methods than just Run. We execute the method using our own code, not RazorEngine.

A custom IActivator might give us the flexibility to accomplish 1. We might be able to cram our entire Template process into Run to accomplish 3.

But, I'm not really sure of a means to accomplishing (2) without rewriting existing code in RazorEngine.

matthid commented 7 years ago

Without a code sample it's really hard to know what you are trying to do. For example the whole idea of Razor is to transform a template to a 'single' method to run.

but the template instance is not actually run

How can a template modify anything without running the single created method?

mtdaniels commented 7 years ago

We surely break the "single method to run" idea.

For instance, our base template has the equivalent of: public abstract IParameter[] Parameters{get;}

Then, our template could have: @functions { public override IParameter[] Parameters {get{return new[]{new Parameter("SomeParameter")};} }

Then, we can compile and create an instance of the template, get the parameters, display them (in a UI or something), get parameters from a user, pass them into the template (using an initialize method or otherwise), and then finally run the template.

All we really want out of RazorEngine is code generation and compilation.