Sunday, February 18, 2007

Using Velocity in .Net via IKVM

The Velocity template engine has been a core library used in many Java frameworks over the years. There are a few free template engines available that are written in C#. However, they do not seem to have the level of support and development activity that Velocity has. Codesmith seems to be the leader in the .Net world, but it is not free. Since Velocity is written in Java, it cannot directly be used by .Net code without some conversion. I used IKVM to translate the velocity.jar file into a .Net dll. At this point I was not sure if the converted Velocity library would work. My concern was that Velocity operates by processing a context that contains objects (standard and application-specific) that are used to replace references in a template. I thought there might be a problem in passing .Net objects to the Java library. It seems that on most occasions when I think IKVM cannot do something, it simply just works. This is one of those situations. I coded up a test based on the velocity user guide sample (written in VB.Net instead of Java) and it worked. Great, now for something actually useful. What I wanted to do was generate a data transfer object by obtaining column names and types from an instance of SQL server (I used SQL Express). I already had a database related to a little home banking application I have been working on. The DTO object I want to generate consists of a VB class with public properties representing the table columns. The VB.Net code can be downloaded here.


The velocity template file (dto.vm) contains:

'
' Generated on $date
'

Class ${tablename}DTO

#foreach( $val in $columns )
Private _$val.GetColName() As $val.GetColType()
#end

#foreach( $val in $columns )
Public Property ${val.GetColName()}() As $val.GetColType()
Get
return _$val.GetColName()
End Get
Set
_$val.GetColName() = value
End Set
End Property

#end
End Class


The $references are replaced by the corresponding data that was placed into the Velocity context in the VB.Net code. The Velocity Template Language supports a nice set of features. You can read about all the details in the user guide. When the code is executed, the following is written to the console:

'
' Generated on 2/18/2007 9:18:41 AM
'

Class TransactionsDTO

Private _TransactionID As Int32
Private _CategoryID As Int32
Private _Amount As Double
Private _Description As String
Private _InsertDate As DateTime
Private _TransactionDate As String

Public Property TransactionID() As Int32
Get
return _TransactionID
End Get
Set
_TransactionID = value
End Set
End Property

Public Property CategoryID() As Int32
Get
return _CategoryID
End Get
Set
_CategoryID = value
End Set
End Property

Public Property Amount() As Double
Get
return _Amount
End Get
Set
_Amount = value
End Set
End Property

Public Property Description() As String
Get
return _Description
End Get
Set
_Description = value
End Set
End Property

Public Property InsertDate() As DateTime
Get
return _InsertDate
End Get
Set
_InsertDate = value
End Set
End Property

Public Property TransactionDate() As String
Get
return _TransactionDate
End Get
Set
_TransactionDate = value
End Set
End Property

End Class



Velocity's template language allows you to quickly create useful templates. This example shows generating a simple DTO, however much more complex code can be generated. I should point out that there is a port of Velocity from Java to C# (NVelocity). However, there has not been a release of this library since 2003. Activity on this project seems to be non-existent during the last few years. The original Java version however is constantly being updated, improved, and documented.