This tooling console application assembly contains the Beef code generation capabilities.
Code generation is proposed as a means to greatly accelerate application development where standard coding patterns can be determined and the opportunity to automate exists.
Code generation is intended to bring the following benefits:
- Acceleration of development;
- Consistency of approach;
- Simplification of implementation;
- Reusability of layering and framework;
- Evolution of approach over time;
- Richness of capabilities with limited effort.
There are generally two types of code generation:
- Gen-many - the ability to consistently generate a code artefact multiple times over its lifetime without unintended breaking side-effects. Considered non-maintainable by the likes of developers as contents may change at any time; however, can offer extensible hooks to enable custom code injection where applicable.
- Gen-once - the ability to generate a code artefact once to effectively start the development process. Considered maintainable, and should not be re-generated as this would override custom coded changes.
Beef primarily leverages Gen-many as this offers the greatest long-term benefits.
Both entity-driven and database-driven are supported; similar to the following image.
The base code-generation tooling is enabled by OnRamp
; the OnRamp code-generation tooling is composed of the following:
- Configuration - data used as the input for to drive the code-generation and the underlying templates.
- Templates - Handlebars templates that define a specific artefact's scripted content.
- Scripts - orchestrates one or more templates that are used to generate artefacts for a given configuration input.
The code-gen is driven by a configuration data source, in this case YAML, JSON or XML.
The two supported configurations are:
- Entity-driven - the configuration root definition is
Entity.CodeGenConfig
. All the related types are found here. - Database-driven - the configuration root definition is
Database.CodeGenConfig
. All the related types are found here.
The Beef templates (as per OnRamp
) are defined using Handlebars and its syntax, or more specifically Handlebars.Net.
The template files have been added as embedded resources within the project to enable runtime access. The Beef standard templates can be found here.
To orchestrate the code generation, in terms of the Templates to be used, a YAML-based script-like file is used. The Beef standard scripts can be found here. The Script files have been added as embedded resources within the project to enable runtime access.
The entity-driven gen-many code generation is enabled by an Entity configuration file that is responsible for defining the characteristics used by the code-gen tooling. The hierarchy is as follows:
└── CodeGeneration
└── Entity(s)
└── Property(s)
└── Const(s)
└── Operation(s)
└── Parameter(s)
Configuration details for each of the above are as follows:
CodeGeneration
- YAML/JSON or XMLEntity
- YAML/JSON or XMLProperty
- YAML/JSON or XMLConst
- YAML/JSON or XMLOperation
- YAML/JSON or XMLParameter
- YAML/JSON or XML
The Entity configuration supported filenames are, in the order in which they are searched by the code generator: entity.beef.yaml
, entity.beef.json
, entity.beef.xml
, {Company}.{AppName}.xml
.
The Entity configuration is defined by a schema, YAML/JSON-based entity.beef.json and XML-based codegen.entity.xsd. These schema should be used within the likes of Visual Studio when editing to enable real-time validation and basic intellisense capabilities.
There are two additional configuration files that share the same schema:
- Reference Data - used to define (configure) the Beef-specific Reference Data. Supported filenames are in the order in which they are searched by the code generator:
refdata.beef.yaml
,refdata.beef.json
,refdata.beef.xml
,{Company}.{AppName}.RefData.xml
. - Data Model - used to define (configure) basic data model .NET classes typically used to represent internal/backend contracts that do not require the full funcionality of a Beef entity. Supported filenames are in the order in which they are searched by the code generator:
datamodel.beef.yaml
,datamodel.beef.json
,datamodel.beef.xml
,{Company}.{AppName}.DataModel.xml
.
The database-driven code generation is enabled by a Database configuration file that is responsible for defining the characteristics used by the code-gen tooling. The hierarcy is as follows:
└── CodeGeneration
└── Query(s)
└── QueryJoin(s)
└── QueryJoinOn(s)
└── QueryWhere(s)
└── QueryOrder(s)
└── Table(s)
└── StoredProcedure(s)
└── Parameter(s)
└── Where(s)
└── OrderBy(s)
└── Execute(s)
└── Cdc(s)
└── CdcJoin(s)
└── CdcJoinOn(s)
Configuration details for each of the above are as follows:
- CodeGeneration - YAML/JSON or XML
- Query - YAML/JSON or XML
- QueryJoin - YAML/JSON or XML
- QueryJoinOn - YAML/JSON or XML
- QueryWhere - YAML/JSON or XML
- QueryOrder - YAML/JSON or XML
- Table - YAML/JSON or XML
- StoredProcedure - YAML/JSON or XML
- Parameter - YAML/JSON or XML
- Where - YAML/JSON or XML
- OrderBy - YAML/JSON or XML
- Execute - YAML/JSON or XML
- Cdc - YAML/JSON or XML
- CdcJoin - YAML/JSON or XML
- CdcJoinOn - YAML/JSON or XML
The Database configuration supported filenames are, in the order in which they are searched by the code generator: database.beef.yaml
, database.beef.json
, database.beef.xml
, {Company}.{AppName}.Database.xml
.
The Database configuration is defined by a schema, YAML/JSON-based database.beef.json and XML-based codegen.table.xsd. These schema should be used within the likes of Visual Studio when editing to enable real-time validation and basic intellisense capabilities.
Finally, this is not intended as an all purpose database schema generation capability. It is expected that the tables pre-exist within the database. The database schema/table catalog information is queried from the database directly during code generation, to be additive to the configuration, to minimise the need to replicate (duplicate) column configuration and require on-going synchronization.
The Beef.CodeGen.Core
can be executed as a console application directly; however, the experience has been optimized so that a new console application can reference and inherit the capabilities.
Additionally, the Database
related code-generation can be (preferred method) enabled using Beef.Database.Core
. This will internally execute Beef.CodeGen.Core
to perform the code-generation task as required.
The following commands are available for the console application (the enablement of each can be overridden within the program logic).
Command | Description |
---|---|
Entity |
Performs code generation using the entity configuration and EntityWebApiCoreAgent.xml script. |
RefData |
Performs code generation using the refdata configuration and RefDataCoreCrud.xml script. |
Database |
Performs code generation using the Company.AppName.Database.xml configuration and Database.xml script. |
DataModel |
Performs code generation using the Company.AppName.DataModel.xml configuration and DataModelOnly.xml script. |
All |
Performs all of the above (where each is supported as per set up). |
Additionally, there are a number of command line options that can be used.
Business Entity Execution Framework (Beef) Code Generator tool.
Usage: Beef.CodeGen.Core [options] <command>
Arguments:
command Execution command type.
Allowed values are: Entity, Database, RefData, DataModel, All.
Options:
-?|-h|--help Show help information.
-s|--script Script orchestration file/resource name.
-c|--config Configuration data file name.
-o|--output Output directory path.
-a|--assembly Assembly containing embedded resources (multiple can be specified in probing order).
-p|--param Parameter expressed as a 'Name=Value' pair (multiple can be specified).
-cs|--connection-string Database connection string.
-cv|--connection-varname Database connection string environment variable name.
-enc|--expect-no-changes Indicates to expect _no_ changes in the artefact output (e.g. error within build pipeline).
-sim|--simulation Indicates whether the code-generation is a simulation (i.e. does not create/update any artefacts).
-x2y|--xml-to-yaml Convert the XML configuration into YAML equivalent (will not codegen).
The Program.cs
for the new console application should be updated similar to the following. The Company
and AppName
values are specified, as well as optionally indicating whether the Entity
, RefData
, Database
and/or DataModel
commands are supported.
public class Program
{
static int Main(string[] args) => CodeGenConsole
.Create("Company", "AppName") // Create the Console setting Company and AppName.
.Supports(entity: true, refData: true) // Set which of the Commands are supported.
.Run(args); // Run the console.
}
To run the console application, simply specify the required command; e.g:
dotnet run entity -- Default filename: Company.AppName.xml
dotnet run refdata -- Default filename: Company.RefData.xml
dotnet run datamodel -- Default filename: Company.AppName.DataModel.xml
dotnet run all -- All of the above
-- Override the configuration filename.
dotnet run entity --configFile configfilename.xml
As described above Beef has a set of pre-defined (out-of-the-box) Scripts and Templates. These do not have to be used, or additional can be added, where an alternate code-generation outcome is required.
To avoid the need to clone the solution and update, add the Templates
and Scripts
folders into the new console application and embed the required resources. The underlying Beef.CodeGen.Core
will probe the embedded resources and use the overridden version where provided, falling back on the Beef version where not overridden.
One or more of the following options exist to enable personalization.
Option | Description |
---|---|
Config | There is currently no means to extend the underlying configuration .NET types directly. However, as all the configuration types inherit from ConfigBase the ExtraProperties hash table is populated with any additional configurations during the deserialization process. These values can then be referenced direcly within the Templates as required. To perform further changes to the configuration at runtime an IConfigEditor can be added and then referenced from within the corresponding Scripts file; it will then be invoked prior to the code generation enabling further changes to occur. The ConfigBase.CustomProperties hash table is further provided to enable additional properties to be set and referenced in a consistent manner. |
Templates | Add new Handlebars file, as an embedded resource, to the Templates folder (add where not pre-existing) within the project. Where overriding use the same name as that provided out-of-the-box; otherwise, ensure the Template is referenced by the Script . |
Scripts | Add new Scripts YAML file, as an embedded resource, to the Scripts folder (add where not pre-existing) within the project. Use the Inherits attribute where still wanting to execute the out-of-the-box code-generation. |
The Beef.Demo.Codegen
provides an example (tests the capability) of the implementation.
Code | Description |
---|---|
TestConfigEditor.cs |
This implements IConfigEditor and demonstrates ConfigBase.TryGetExtraProperty and ConfigBase.CustomProperties usage. |
TestCodeGenerator.cs |
This inherits from CodeGeneratorBase<TRootConfig, TGenConfig> overriding the SelectGenConfig to select the configuration that will be used by the associated Template. |
Test_cs.hbs |
This demonstrates how to reference both the ExtraProperties and CustomProperties using Handlebars syntax. This file must be added as an embedded resource. |
TestScript.xml |
This demonstrates the required configuration to wire-up the previous so that they are leveraged apprpropriately at runtime. This file must be added as an embedded resource. |
Finally the Program.cs
will need to be updated similar as follows to use the new Scripts resource.
return CodeGenConsoleWrapper
.Create("Beef", "Demo")
.Supports(entity: true, refData: true, dataModel: true)
.EntityScript("TestScript.xml") // <- Overrides the Script name.
.RunAsync(args);