.NET Template Organization
So, now that you know where I’m going with this – language neutral templates – I want to step back to the basics. Even if you don’t want to build language neutral templates, there are things to learn along the way about making good XML literal templates, and why this approach might be better than your current code gen mechanism. Note, the examples in this post are NOT language neutral. Not surprisingly, there are specific requirements for language neutral templates and I want to show basic templating with XML literals, then the language neutral templates.
If you look at the XML literal sample I posted a few days ago you’ll notice that the entire contents of the output DataPortalFetch method is created within the template method “MemberDataPortalFetch.” This provide important organization as the most common challenging task in code generation is “I have a problem in my output code right here, how do I find where that is in the template. In a simple template this isn’t too hard, but in more complex templates such as CSLA it can be quite challenging.
Creating templates with an extremely predictable structure is very valuable in creating maintainable templates. To start with each template should have a one to one correspondence with an output class.
Within this class, the mechanism of the predictable structure is one of the primary differences from codes that are code with template segments (XML literal code generation) and templates with code segments (ASP.NET style template). In an ASP.NET template, the template must parallels the output and this organizes the template. In an XML literal template, you provide the organization with Visual Studio then providing navigation. Code is organized my regions, nested classes and member. Each is its own method preceded by Region, NestedClass or Member. This organizes the template. The entry points create a hierarchy working down to the local code (navigation mechanism #1):
Protected Overrides Function GenerateFile() As String
Public Class <%= mObjectData.ClassName %>
Inherits BusinessBase(Of <%= mObjectData.ClassName %>)
<%= RegionBusinessMethods() %>
<%= RegionValidationRules() %>
<%= RegionAuthorizationRules() %>
<%= RegionFactoryMethods() %>
<%= RegionDataAccess() %>
<%= RegionExists() %>
#Region "Business Methods"
Private Function RegionBusinessMethods() As String
#Region " Business Methods "
<%= From prop In mObjectData.Properties Select MemberPropertyFields(prop) %>
<%= From child In mObjectData.Children Select MemberChildFields(child) %>
<%= From prop In mObjectData.Properties Select MemberPropertyAccess(prop) %>
<%= From child In mObjectData.Children Select MemberChildAccess(child) %>
<%= MemberIsValid() %>
<%= MemberIsDirty() %>
<%= MemberGetId() %>
The carefully named methods also allow you to use alphabetical tools in Visual Studio including the combo box in the upper right of the editor and a class diagram (navigation mechanism #2) which works only because you can predict the name of the member you want from the name of the output member and no other members begin with “Member”, “Region” or “NestedClass”
The third navigation approach is that the template matches the structure of the output as closely as practical. Thus if the output has a region names “Business Methods” the template does as well. The order of items in the template is top to bottom closely paralleling the order of the output. This allows you to cruise down in the file.
Template organization is the first step to great templates.