Closed lars-erik closed 5 years ago
When configured in "AppData Models" mode, the ModelsBuilder "just" generates the files and does not compile them, nothing. At the moment they go into ~/App_Data/Models (hence the name) but IIC you'd like to be able to put them somewhere else. That could be a config option, however I have one question: would that "somewhere" be under the website root, or do you have other places in mind? One could consider writing files outside the website root a potential security risk... though, not sure - you'd probably want to do it in DEV only, not PROD.
Now about "providerization"... we need to find the proper level. The "builtin engine" really is 10% detecting content type changes & triggering generation, and 90% building models. That task alone, in ModelsBuilder, means parsing the existing, non-model, partial class definitions, all sorts of things... that you would do differently.
I need to think about it, but I cannot find a simple point in the ModelsBuilder where stuff could be "providerized". OTOH I think that we probably can define a very lightweight interface in Core, for a generator to implement, and then it would be the entire generator that would be replaced.
Thoughts
Have created related task http://issues.umbraco.org/issue/U4-7355 for 7.4 so we take this in account.
Meaning this issue is about pluggability only, and the discussion re. files location has been moved over to another issue: https://github.com/zpqrtbnk/Zbu.ModelsBuilder/issues/74
These seem pretty similar, and swapping out my doctype abstractions with yours would make them more or less identical in interface:
https://github.com/zpqrtbnk/Zbu.ModelsBuilder/blob/master/Zbu.ModelsBuilder/Building/CodeDomBuilder.cs
https://github.com/lars-erik/Umbraco.CodeGen/blob/master/Umbraco.CodeGen/Generators/ClassGenerator.cs
If I understand correctly you started using CodeDom somewhere along the way too? :)
Wanted to, then found it simpler to just write C# text code.
So CodeDomBuilder is just litter? Mine would plug right in..
This factory class composes a class builder that makes simple content type wrappers with interfaces for mixins, and concrete implementations.
Output:
The factory could easily be wrapped with something that accepts a stringbuilder instead.
Haven't gone far in, but this seems like the place:
var builder = new TextBuilder(typeModels, parseResult, Config.ModelsNamespace);
Turns out I might be able to abstract the builder ... which would be the first step towards being able to switch builders ... they key would be the Generate
method... with a signature similar to
public void Generate(StringBuilder sb, TypeModel typeModel);
And then of course you'd have to use ModelsBuilder's TypeModel
data to generate.
Would that make any sense?
Sounds good!
I just noticed you had a Generate(CodeDomSomething x)
in your prototype code, so I figured you could vary. ;)
But either way is good.
I see what you mean. CodeDom generation writes to a CodeNamespace, not to text files, that's the point of CodeDom generation. Silly me. Still, I think we need to be able to save the generated code somewhere, somehow, so people can have a look at it - otherwise debugging can turn into a nightmare.
I have no idea whether CodeDom can output C# source code.
Another thing to have in mind: I initially created the CodeDomBuilder because I thought that building actual code trees would be more elegant and faster than writing C# code to a StringBuilder
. Ideally, there would be a RoslynBuilder that would use Roslyn's SyntaxFactory
to create actual code trees (and Roslyn knows how to output those trees into text files).
However, this post makes me think. IIC, creating code trees is much more verbose, and generally slower, than writing/parsing raw C# code.
At this point, I'm seriously considering merging my Builder
and TextBuilder
class and deciding that ModelsBuilder generates via C# code text, full stop. Thoughts?
Regarding performance, this will only ever happen on content type save, so a few milliseconds more there won't really hurt, will it?
I generate text from a CodeDom namespace using Microsoft.CSharp.CodeProvider. See the Generate method here: https://github.com/lars-erik/Umbraco.CodeGen/blob/7.4/Umbraco.CodeGen/CodeGenerator.cs
The way I generate models could be done using only text, but what I really like about my generator is that it has composite code builders. That means you can extend or modify the way code is generated, but still re-use the stuff you don't need to change. Have a look at the CreateGenerator method in the generator factory we currently use: https://github.com/lars-erik/Umbraco.CodeGen/blob/7.4/Umbraco.CodeGen/Generators/GenerateOnlyGeneratorFactory.cs
Whether the provider I make for ModelsBuilder has to output text or a CodeDom object is really not very important to me. I can keep the code from the CodeGenerator.Generate method. (CodeProvider.GenerateCodeFromNamespace)
Meaning you can decide whatever you want about the Builder and TextBuilder classes. :)
Right?
So IIC you can use CodeDom and be happy with the Generate(StringBuilder, TypeModel)
signature? If that's the case, then... OK I don't need to close that door ;-)
Yep. :)
Closing this issue as I think it has been superceeded by #94.
Hi Stephane,
I'm starting to realize I'm completely lagging behind on typed models and obviously "losing market" completely since the models builder is being integrated to 7.4.
However, I've been looking at this one and it seems to be more or less the same, but with slightly other users in mind.
Could you add an option to configure where you want files to be generated, and just don't touch them? (Compile etc.)
IE. Put my files at the physically relative directory ../../../SomeFolder.
Would it also be possible to "providerize" the code generators, so one could override the default generation?
Not sure how much you've looked at the codegen source, but in the current master branch it's been stripped down to pure code generation, and I'd really like to keep using files looking like this.
I wouldn't mind just plugging it into the "built-in engine", though.
Anything I could help out with, or just donate from my project?