FinalBuilder4 action for running CodeSmith templates

The past week I was busy creating an automated template based system for generating Developer Express' XPO source code. Heart of the system is based on CodeSmith and my custom templates (perhaps more details about the system in a later post).
Once I've finished all my templates for generating fine XPO code (everything is really powerful and flexible, trust me :-)) I had to find a way to automate the (re)build since there is not only one template.

One of the option was to use CodeSmithGenerator that spits out code based on input parameters in XML file that is part of your project (the same system is used by MSDataSetGenerator). The only weakness of this approach is that it requires several clicks if you have more than one template.

So I went with out of IDE build process because I like to do everything within the single action. Again, I faced three choices:

  1. Use good old command line bat file.
    This would do, but feedback is poor and it won't do handle Visual Source Safe.
  2. Use MSBuild tool that comes with .net 2.
    CodeSmith 3.2 comes with custom MSBuild taks that takes care of running the template generator. However, MSBuild is rather limited out of the box - no UI and no VSS control.
  3. FinalBuilder4. This is great automated build tool and perfect for me in this case. The only drawback is that it doesn't know how to run CodeSmith generator. On the other hand it does everything else.

I went with option 3. But I did have to build an action for running CodeSmith generator. Fortunately for me, build custom actions for FB4 is really simple (I did it before for XSD tool). After a hour or so of coding in VBScript (the easiest way to create a simple FinalBuilder4 action) CodeSmith action was created. The settings screen looks like this:

There are is no support for merging at this point simply because I didn't need it. I might add it in next version.

The result is that I simply invoke FinalBuilder4 via a shortcut and it does everything for me (check out files before, runs CodeSmith generator and check in files after).

You can find CodeSmith action here.

CodeSmith merge functionality for csproj files

If you are seriously using CodeSmith you will know about the merge functionality. True, with introduction of partial classes in .net 2 the need for merging is greatly reduced, but still it is very useful.

How it works, very briefly?

You define markers (start and end, i.e. #region Start and #endregion in C#) in source code and when building template output you pass the marker reference (in this case you would pass a command line argument (it works only from command line) like this: /merge:InsertRegion="RegionName=Start;Language=C#". CodeSmith will inject template output between those two markers and will preserve the rest of source code. There are also different merge strategies (insert and preserver out of the box) and moreover, you can define your own if you need to. The same goes for source code support: C#, VB.NET and T-SQL are supported out of the box. If you need additional type of source code you are free to add your own marker definitions using regular expressions. Everything is adequately documented in help file and I won't repeat it here.

Creating my own target type

Today I realized that I need to inject some text into csproj file itself. The problem is that csproj file (C# project file) isn't natively supported by CodeSmith. Heck, no problem - CodeSmith is extensible. So I went creating my own merging target: csproj. Since csproj file is an XML one I will define my start marker as <!-- NAME--> and end marker as <!-- EndRegion-->. Here are the necessary steps:

  • Open CodeSmithEngine.config file located in C:\Documents and Settings\All Users\Application Data\CodeSmith\v3.2 (note that version number might differ)
  • Add the following XML code right after the last node </languageRegionDefinitions>:

    <languageRegionDefinitions>
      <languageKeyList>
        <key>csproj</key>
      </languageKeyList>
      <regionStartRegex>^[ \t]*&lt;!--[\s\t]*(?&lt;name&gt;.*)--&gt;</regionStartRegex>
      <regionEndRegex>^[ \t]*&lt;!--[\s\t]*(?i:EndRegion).*--&gt;</regionEndRegex>
    </languageRegionDefinitions>

  • Save

That's it. I just need to insert markers into the target csproj file and run my template over it. Note that the merge parameter is slightly different as target type has changed to csproj: /merge:InsertRegion="RegionName=Start;Language=csproj"

Have fun using and extending merge functionality!

XPO2 supports generics and nullables out of the box

XPO2 (currently in beta) supports both generics and nullables out of the box. I did a simple test by creating a generic XpCollection:

XpCollection<SomeEntity> coll = new XpCollection<SomeEntity>(session1);
SomeEntity se = coll[0];

SomeEnitity had also a nullable int? field/property which performed as one would expect. Great. XPO2 seems more and more appealing to me.

CodeSmith 3.2 is released

While it doesn't have many new features it has two really helpfull features - it runs under .net 2.0 and has a CodeSmith MSBuild task.

I think that generics and perhaps iterators (C#) will have a major impact on templete code you are writting. At least for me it will. This is so good that I'll write a template using generics right now, just for fun.

Follow this link to get CodeSmith:
http://community.codesmithtools.com/blogs/announcements/archive/2006/01/30/9298.aspx