TrackableEntities / EntityFrameworkCore.Scaffolding.Handlebars

Scaffold EF Core models using Handlebars templates.
MIT License
209 stars 53 forks source link

"if eq" support in templates #69

Closed omatrot closed 5 years ago

omatrot commented 5 years ago

I'm trying to customize the provided templates in order to integrate dcerialize. It seems to me that I can't test for a simple equality to customize the generated code:

{{spaces 2}}@autoserializeAs(() =>
{{#if (eq property-type "number")}}
Number
{{/if}}
{{#if (eq property-type "string")}}
String
{{/if}}
)

The template does not compile:

HandlebarsDotNet.HandlebarsCompilerException: An unhandled exception occurred while trying to compile the template ---> HandlebarsDotNet.HandlebarsCompilerException: An unhandled exception occurred while trying to compile the template ---> HandlebarsDotNet.HandlebarsCompilerException: An unhandled exception occurred while trying to compile the template ---> System.ArgumentException: Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
   at System.Reflection.RuntimeMethodInfo.CreateDelegateInternal(Type delegateType, Object firstArgument, DelegateBindingFlags bindingFlags)
   at HandlebarsDotNet.Compiler.SubExpressionVisitor.GetHelperDelegateFromMethodCallExpression(MethodCallExpression helperCall)
   at HandlebarsDotNet.Compiler.SubExpressionVisitor.VisitSubExpression(SubExpressionExpression subex)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
   at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.VisitConditional(ConditionalExpression node)
   at System.Linq.Expressions.ConditionalExpression.Accept(ExpressionVisitor visitor)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitBlockExpressions(ExpressionVisitor visitor, BlockExpression block)
   at System.Linq.Expressions.ExpressionVisitor.VisitBlock(BlockExpression node)
   at System.Linq.Expressions.BlockExpression.Accept(ExpressionVisitor visitor)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitBlockExpressions(ExpressionVisitor visitor, BlockExpression block)
   at System.Linq.Expressions.ExpressionVisitor.VisitBlock(BlockExpression node)
   at System.Linq.Expressions.BlockExpression.Accept(ExpressionVisitor visitor)
   at HandlebarsDotNet.Compiler.FunctionBuilder.Compile(IEnumerable`1 expressions, Expression parentContext, String templatePath)
   --- End of inner exception stack trace ---
   at HandlebarsDotNet.Compiler.FunctionBuilder.Compile(IEnumerable`1 expressions, Expression parentContext, String templatePath)
   at HandlebarsDotNet.Compiler.IteratorBinder.GetDynamicIterator(Expression contextParameter, IteratorExpression iex)
   at HandlebarsDotNet.Compiler.IteratorBinder.VisitIteratorExpression(IteratorExpression iex)
   at System.Linq.Enumerable.SelectIListIterator`2.ToArray()
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
   at System.Linq.Expressions.Expression.Block(Type type, IEnumerable`1 variables, IEnumerable`1 expressions)
   at System.Linq.Expressions.BlockExpression.Accept(ExpressionVisitor visitor)
   at HandlebarsDotNet.Compiler.FunctionBuilder.Compile(IEnumerable`1 expressions, Expression parentContext, String templatePath)
   --- End of inner exception stack trace ---
   at HandlebarsDotNet.Compiler.FunctionBuilder.Compile(IEnumerable`1 expressions, Expression parentContext, String templatePath)
   at HandlebarsDotNet.Compiler.FunctionBuilder.Compile(IEnumerable`1 expressions, String templatePath)
   --- End of inner exception stack trace ---
   at HandlebarsDotNet.Compiler.FunctionBuilder.Compile(IEnumerable`1 expressions, String templatePath)
   at HandlebarsDotNet.Handlebars.HandlebarsEnvironment.RegisterTemplate(String templateName, String template)
   at EntityFrameworkCore.Scaffolding.Handlebars.HbsTemplateService.RegisterPartialTemplates()
   at EntityFrameworkCore.Scaffolding.Handlebars.HbsTypeScriptModelGenerator.GenerateModel(IModel model, String namespace, String contextDir, String contextName, String connectionString, ModelCodeGenerationOptions options)
   at Microsoft.EntityFrameworkCore.Design.Internal.DatabaseOperations.ScaffoldContext(String provider, String connectionString, String outputDir, String outputContextDir, String dbContextClassName, IEnumerable`1 schemas, IEnumerable`1 tables, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContextImpl(String provider, String connectionString, String outputDir, String outputDbContextDir, String dbContextClassName, IEnumerable`1 schemaFilters, IEnumerable`1 tableFilters, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_1.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
An unhandled exception occurred while trying to compile the template

I think I've uderstood that this is because I need to register a helper because the built-in helpers just works for true or false evaluation.

Is there a trick to do that or should we modify the HandleBar.NET Code ?

tonysneed commented 5 years ago

My framework supports adding Handlebars helpers. See the project ReadMe for instructions. (Note this does not work with the EF Core Power Tools.)

For customizing the property types, there is also an interface you can implement. (I can provide more info on that if you like.)

omatrot commented 5 years ago

For customizing the property types, there is also an interface you can implement. (I can provide more info on that if you like.)

If you think this would make dcerialize integratation easier , I would.

tonysneed commented 5 years ago

What you need to do is copy and rename TypeScriptHelper.cs. Just update the TypeName method to return desired TypeScript types as strings.

Then in your ScaffoldingDesignTimeServices class after calling AddHandlebarsScaffolding, register your class as follows:

services.AddSingleton<ITypeScriptHelper, MyTypeScriptHelper>();
omatrot commented 5 years ago

Thanks for that I'll see what I can do.