Additional class-files for SelfServicing

Posts   
 
    
teplas
User
Posts: 7
Joined: 27-Apr-2016
# Posted on: 27-Apr-2016 14:06:41   

Hi,

we would like to generate 2 files for every entity class instead of just one ("entity.template").

The output should look like this:

\EntityClasses\ OneEntity.cs OneEntity.partial.cs AnotherEntity.cs AnotherEntity.partial.cs ...

I'm unable to figure out how to accomplish this, specifically how to add a template for another set of files to generate (the *.partial.cs files).

Any hint how to to this? Thanks.

LLBLGen Pro 4.2 (0316) SelfServicing Template .NET 4.5.1 (planned to compile against 4.6.1) DBMS: Oracle 12c

Walaa avatar
Walaa
Support Team
Posts: 14986
Joined: 21-Aug-2005
# Posted on: 27-Apr-2016 18:50:01   

Why do you want to do that? I mean what will be generated in the partial class, that can not be in the main class file?

teplas
User
Posts: 7
Joined: 27-Apr-2016
# Posted on: 28-Apr-2016 12:25:54   

We would prefer to have separate files for generated code and hand-written code, because this is the .NET/C# way of doing things.

Walaa avatar
Walaa
Support Team
Posts: 14986
Joined: 21-Aug-2005
# Posted on: 28-Apr-2016 18:42:44   

You'd better add these partial class files manually in the project when you need them. But having them generated for you, would overwrite what you have hard coded, on every code generation process.

teplas
User
Posts: 7
Joined: 27-Apr-2016
# Posted on: 02-May-2016 08:30:07   

Of course we can do that, but it's not efficient for large ORM models.

I expected that I could create a file which consists more or less of one single "user code region" that is retained when generating the model.

Any hints on how to actually do this kind of thing instead of just questioning the purpose?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39760
Joined: 17-Aug-2003
# Posted on: 02-May-2016 09:45:40   

teplas wrote:

Of course we can do that, but it's not efficient for large ORM models.

I expected that I could create a file which consists more or less of one single "user code region" that is retained when generating the model.

Any hints on how to actually do this kind of thing instead of just questioning the purpose?

Generating the files would only save you creating them, but at the same time give the problem that you have files without any code which still need to be maintained (the files to which you don't add any code to). So basically you want to scaffold a lot of files which have no real meaning. I would strongly advice against that. Add the partial class file when you need it, create a separate folder in the generated code project and add the extension classes there. What you want is not recommended, because you end up with generated code someone else has to work with and who might wonder why there are so many files which are empty.

Selfservicing actually has build in what you want: it has a 2-class scenario template set, where the derived class of the entity (CustomerEntity) is meant for user code and the actual entity class (CustomerEntityBase), contains the framework generated code. (this stems from the original design in the time when there was no such thing as a partial class, and this was the only option to offer extensibility) Adding yet another file is overkill.

If you insist on having partial classes generated, you can do so of course: add a templatebindings file with a template which generates an empty partial class for an entity. You do that in the templatebindings viewer where you create a new templatebindings file and define a templateID<->file binding, the templateid and file are up to you, as long as the file is reachable by the designer (so e.g. inside the folder you've specified as 'additional templates' folder in the project settings.

As your template is very simple, you can use TDL templates. (so blabla.template files). See the SDK docs for details.

When you save the templatebindings file inside the designer, you should 'refresh the code generation meta data' which can be done with the green button on the toolbar or in the tools menu. The templatebindings viewer should now have your templatebindings file listed and when selected you see the templatebinding you defined and the filename likely in red. Double click it will create the file and open it in the editor. Add: (if you chose TDL as template language)


namespace <[RootNamespace]>.EntityClasses
{
    public partial class <[CurrentEntityName]>Entity
    {
    }
}

Then you have to add a task which executes the template. You're using v4.2 so you do that in the code generation configuration dialog, tab 3: there you add a new task which executes your template with the templateID you've given in the template bindings file you've created.

Add a 'SD.Tasks.Base.ConsumeTDLTemplate' task.

Set 'destinationFolder' to [driverShortName]\EntityClasses Set 'filenameFormat' to [elementName]Entity.partial.[extension] Set 'failWhenExistent' to true (this is very important, as you want to generate them once) Set 'templateID' to the templateID you defined in your templatebindings file Set 'emitType' to allEntities

Save the preset, you should now be able to generate your classes, but again, it's overkill.

Frans Bouma | Lead developer LLBLGen Pro
teplas
User
Posts: 7
Joined: 27-Apr-2016
# Posted on: 02-May-2016 12:06:50   

Hi Otis,

thank you very much for your how-to! I manged to get it working as you explained.

It is working, but I have one more question you might be able to help me (or at least confirm if it's not possible):

Is it possible (and if so how), to influence the "csproj" creator to emit certain files as "DependentUpon"?

It would look like this:

<Compile Include="EntityClasses\OneEntity.partial.cs">
  <DependentUpon>OneEntity.cs</DependentUpon>
  <GeneratedBy>LLBLGen Pro</GeneratedBy>
</Compile>

Thanks again for your help!

Walaa avatar
Walaa
Support Team
Posts: 14986
Joined: 21-Aug-2005
# Posted on: 02-May-2016 19:20:44   

The code generators have now support for emiting DependentUpon elements. This is done through a new optional parameter on code generator task performers called dependentUponFileFormat, which uses the same filename characteristics as the filenameFormat parameter. The same logic is used to create a full filename.

There's a new task cache element added, called dependentUponFiles which has per entry as key the file which should get the dependentUpon element in the project file and as value the filename it is dependent upon.

Every task which has the parameter DependentUpon specified with a non-empty value gets its file added to this cache.

The ProjectFileCreator task performer will use the new cache element to emit DependentUpon xml elements in the project file.

In other words: The ProjectFileCreator supports DependentUpon tags. To specify if a generated file A is dependent upon another file B, specify the fileformat of B as the value of the parameter dependentUponFileFormat on the task which generates A.

teplas
User
Posts: 7
Joined: 27-Apr-2016
# Posted on: 03-May-2016 08:37:44   

Hi Walaa,

that sounds exactly what I was looking for. However I'm unable to spot it in LLBLGen 4.2 Pro (0316). Is this new for 5.0 which is still Beta? Or where exactly should I find it?

I checked in the task queue, SD.Tasks.SelfServicing.VsNetProjectFileCreator, but no such parameter exists.

EDIT: OK, I re-read your answer and found out I'm looking in the wrong place. But I also couldn't find the property in the SD.Tasks.Generic.EntityClassGenerator (CodeEmitter).

Trying to add it manually (Notepad) to the preset file didn't pick it up in the GUI.

On the other hand, I found this property mentioned in the CHM online help, so I guess my version should already support this feature.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39760
Joined: 17-Aug-2003
# Posted on: 03-May-2016 15:40:36   

It's indeed on the code generator tasks. The task you refer to is a predefined task with pre-filled in parameters. But this isn't a problem. The task you added to run your new template needs the parameter set as those files are depending on other files. You added for that a SD.Tasks.Base.ConsumeTDLTemplate task, I presume? that task contains the parameter.

So your task has as filename format '[elementName]Entity.partial.[extension]'. For dependentUponFilenameFormat for your task you specify '[elementName]Entity.[extension]'. This will tell the code generator that files generated with your task depend on other files, and it uses the format specification of '[elementName]Entity.[extension]' to construct the filename. This will result in your .partial.cs file be placed below the entity classes.

Frans Bouma | Lead developer LLBLGen Pro
teplas
User
Posts: 7
Joined: 27-Apr-2016
# Posted on: 03-May-2016 16:35:02   

Thanks to your help I got one step closer to my goal.

Unfortunately I think the [elementName] is not working in the dependentUponFilenameFormat parameter.

From the source code of the task I see that is is calling into the CreateFilename overload without supplying the elementName but only the extension:

CodeGenerationEngineBase.EmitOutputForElements<EntityDefinition>(...)
-> CreateFilename(string filenameFormat, string extension)

instead of:

-> CreateFilename(string filenameFormat, string extension, string elementName)

Sounds like a bug/omission to me, or is there a reason why it is not calling into the overload with the elementName?

Is there also a reason why it does not support the dependentUponFilenameFormat parameter in the EntityClassesGenerator task?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39760
Joined: 17-Aug-2003
# Posted on: 04-May-2016 10:07:37   

Bug. Design docs clearly state it should be able to transform [elementName], the xml comments on the code generators do too, it calls the wrong method. We'll fix this.

Is there also a reason why it does not support the dependentUponFilenameFormat parameter in the EntityClassesGenerator task?

No, but as these are prefab tasks meant for one thing, we didn't change them to add parameters which aren't to be used.

The task definition you refer to will never produce files which are 'depending' on another file, it's always an additional task which will be depending on them. These tasks are in general created using the 2 general template consume tasks which do have the parameter.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39760
Joined: 17-Aug-2003
# Posted on: 04-May-2016 10:50:02   

Could you please try the attached GeneratorCore.dll which fixes your problem? Copy the dll as administrator into the llblgenpro installation folder, overwriting the existing one.

The issue is in v5 as well, we'll fix this in the v5.0.1 hotfix build.

Attachments
Filename File size Added on Approval
SD.LLBLGen.Pro.GeneratorCore_hotfix_20160504.zip 45,722 04-May-2016 10:50.08 Approved
Frans Bouma | Lead developer LLBLGen Pro
teplas
User
Posts: 7
Joined: 27-Apr-2016
# Posted on: 04-May-2016 12:58:32   

Hi Otis, I can confirm this hotfix is working. Thanks for your help!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39760
Joined: 17-Aug-2003
# Posted on: 04-May-2016 17:53:26   

No problem simple_smile Glad its working.

Frans Bouma | Lead developer LLBLGen Pro