Friday, October 29, 2010

Code Generation Using Custom Item Template, Custom Template Wizard and T4 Engine

Not long time ago, I faced the following requirement:

Company uses custom Data Access Layer, which is developed within company and which does not have any designer tool as Entity Framework or Linq to SQL frameworks have. (Actually the company uses CSLA – but it is modified and cannot be upgraded to latest version even if latest version of CSLA does have any designer tools – but as I know it does not)

The goal is to simplify the creation of new business objects along with data access code.

It is preferred o collect data about business object to be created in some kind of visual form and then generate the business object.

It is also desirable to add business object to Visual Studio solution automatically.

Before they used MyGeneration software, which is separate application running outside of Visual Studio. They had to generate code in it and then manually place the files into VS solution.

After investigating and evaluating few approaches – I stopped on the following:

1) I will use Custom Item Template for Visual Studio to import files into VS solution by using standard VS Add New Item dialog

2) I will use Custom Template Wizard to collect data before adding item to VS solution.

3) I will use T4 Engine to generate artefacts based on data collected in Custom Template Wizard and T4 templates that are predefined. I will use stand alone Custom Template Host

 

The process of business object creation after implementation looked like this:

Developer runs Add New Item dialog in WPF project:

image

Developer selects our Custom Item Template:

image

Developer provides name of business object to create:

image

After developer clicks Add – he is presented with our Custom Template Wizard:

image

Here developer can design the entity – set name, type (along with storage type – DBType, default value, mandatory status, whether it is foreign key – so it must be used in query method as parameter, whether the property is key etc.)

Here is a data model accumulated per business object line (property) :

image

Some pic with tooltips to attributes: image

This form also does validation of data entered by developer:

so When property IsAutoKey, it cannot have default value:

image

Key property cannot be Nullable:

image

Length is only enabled where applicable to data type:

image

image

Validation is applied to property name as well:

image

 

Some other validations:

image

image

image

image

image

When developer finishes entering business object data he can:

1) generate C# objects and add to solution right away

2) OR first generate SQL procedures for business object

 

Let’s review 2nd point.

To farther simplify SQL code execution, the Custom wizard also has ability to connect to DB and retrieve metadata for tables/views from it.

To connect to DB, you must provide parameters:

image

The parameters are stored per machine – so once set up – they will be in effect for any solution / instance of VS.

On this stage we can also import metadata from DB table/view and populate business object properties data.

Just click Import:

image

image

On the popped up window developer can choose table/view to import columns from.

image

When importing from DB table/view, business object name also changes on top:

image

Developer can choose to generate many types of BO – as RO, Writable, Root, Child etc. – every single one will be generated under the hood by using separate T4 template.

image

On any stage of working in Custom Wizard Form – the developer can generate scripts for business object:

image

image

In this window the following scripts are generated:

Table, Select SP, Update SP, Insert SP, Delete SP

The tool can be extended to have more scripts with any contents – as each script is generated from separate T4 template.

Developer can save any script on this stage:

image

(unfortunately developer will have to check in the file to source safe manually)

If developer clicks Execute, he will be able to run script right away:

image

And now the most important part Smile

Developer clicks “OK”, and business objects will be generated and inserted to VS solution at correct place automatically:

image

 

Now the architecture.

 

The code generates from T4 templates -

image

 

Each template is provided with custom data accumulated by wizard. The templates use data to generate code.

image

 

 

Hope this idea helps you deciding to use code generation in your projects : )

 

Now about technical implementation.

 

You (or any developer that wants to start using this) must build the project attached in the end of this article once – and that is it – it registers Custom Wizard, and zips template and copies it to templates directory for VS (see pre and post build events)

 

And

here

you can get complete source code (http://devarchive.net/downloads/CodeGenerator.zip)

 

Enjoy :)

Hope this helps

Kirill

kick it on DotNetKicks.com

9 comments:

XNA Gamer said...

Great! Thank you - it is very good post.

Mayur Mahajan said...

Kirill,

the above post is the best post of all. I wanted to do the same thing and after reading your post i got some hope that this can be done. But I am not getting one thing that :

How do you call your wizard when we select the template from "File-->Add new Item". I wanted to call my own User Interface. How should I achieve this?

Kirill Chilingarashvili said...

Hi Mayur,

you can look for more info here:
http://msdn.microsoft.com/en-us/magazine/cc188697.aspx
please search IWIzard and how to use it.
I did not read the article but it seems it covers that.
I used another reasource from MSDN when created this - but that resource disappeared from msdn :(
That is why the link does not work anymore

anyway try new link - it seems to cover that as well

Cheers,
Kirill

Mayur Mahajan said...

Thanks a lot Kirill. The above link does not covers much about what I wanted but as you suggested I searched for "IWizard and how to use it" and then I got one link which I should mention here for others people trying to that. The link is : "http://www.bluelemoncode.com/post/2012/01/05/Creating-custom-project-and-file-template-with-wizard-for-Visual-Studio.aspx".
This link is very good and explains well about the Wizard creation for the Templates.
Also go through the link "http://blog.devarchive.net/2010/10/code-generation-using-custom-item.html".

Thanks a lot once again Kirill.

Mayur Mahajan said...

Hello,

I am creating a Windows Application. In that I am using T4 Templates.
In T4 templates I have a code which uses some of the static properties and methods of some class from the same project. But when I tries to add reference to that class I get the error as : "[b]Compiling transformation: Invalid reference option: 'WindowsWIzard' -- cannot reference directories[/b]"
The code I have written in .tt file is as follows :

<#@ template language="C#" hostspecific="True" debug="True" #>
<#@ output extension="?" #>
<#@ assembly name="Microsoft.VisualBasic" #>
<#@ assembly name="WindowsWizard" #>
<#@ import namespace="WindowsWizard" #>
<#@ import namespace="WindowsWizard.Templates" #>
<#@ include file="T4Toolbox.tt" #>
<#@ include file="CrudProcedureGenerator.tt" #>
<#@ include file="DeleteProcedureTemplate.tt" #>
<#@ include file="InsertProcedureTemplate.tt" #>
<#@ include file="UpdateProcedureTemplate.tt" #>

<#

CrudProcedureGenerator generator = new CrudProcedureGenerator();
generator.DatabaseName = GenerateCode.SendDBName;
generator.Run();
#>

Here the code block in the standard directives is working fine as I have checked it in another demo application. It is refering above .tt files in include directive. WindowsWIzard is the name of my project i.e. assembly.

Am I doing something wrong? How can I refer refer methods from another Class into the template?

Kirill Chilingarashvili said...

Hi Mayur

Templating Engine can reference assemblies from GAC only - as I remember
If you download code for this article - you will see that in post build event the assemblies are registered in GAC

Regards,
Kirill

Mayur Mahajan said...

Kirill,
Actually I am not getting how you gets the dll from the Windows application and how you are registering your dll into the GAC directly after post build. Will you plz explain this in some detail?
To get the dll I have another Class Library project. Now my application works fine but I have an issue while updating the dll. If I made some changes to my dll then the new changes are not reflected in the Wizard. For this I have unregistered the previous dll and registered the new one. I think the previous dll gets stored in the memory.
Please provide me solution for this issue and plz provide explaination for the above que in first paragraph..!

Thanks & Regards,
Mayur Mahajan

Mayur Mahajan said...

Hi Kirill,

Its been so long we talked. How are you?

Well I wanted to know that can we add more than one Item into the project using Item Template? For eg. Currently it is adding only one Item to my project, suppose WindowsForm1", But I also wanted to add a Global file, GlobalFile.cs, in my project. So how can I create my Item template so that it will add more than one items.

If it is not possible using Item Template to add more than one item, then please suggest a method to do this. I don't want to use Project Template.

Regards,
Mayur Mahajan

Kirill Chilingarashvili said...

Hi Mayur, I am fine thanks,
hope you too.

This is possible - the item template in the sample code for the post also adds more than one item

Here is another sample



MaintenanceScreen
MaintenanceScreen
Creates Maintenance Screen for Protech
CSharp
10
__TemplateIcon.ico



View.xaml
View.xaml.cs
EditView.xaml
EditView.xaml.cs
ViewModel.cs