You must use VB for XML Literal Code Generation. Sorry, that’s life. I don’t have a crystal ball on this, but for now even if you’re a C# programmer you’ve got to suck it up and use VB. The code you output can be VB or C# however, but the template itself has to be written in VB. If you’re allergic to VB, get shots.
So, what does a microcosmic view of a XML literal template look like? I’ve translated a section of a CSLA template. CSLA is Rocky Lhotka’s architecture and this is a version 2.1 because I think it clarifies the template process: Private Function MemberDataPortalFetch() As String Return _<code> Private Overloads Sub DataPortal_Fetch(ByVal criteria As Criteria) Using cn As New SqlConnection(<%= mObjectData.ConnectionStringName %>) cn.Open() Using cm As SqlCommand = cn.CreateCommand cm.CommandType = CommandType.StoredProcedure cm.CommandText = "get<%= mObjectData.ClassName %>" <%= From prop In mObjectData.PrimaryKeys Select _ <code> cm.Parameters.AddWithValue("@<%= prop.Name %>", criteria.<%= prop.Name %>) </code> %> Using dr As New SafeDataReader(cm.ExecuteReader) dr.Read() With dr <%= From prop In mObjectData.Properties Select _ <code> m<%= prop.Name %> = <%= GetReadMethod(prop) %>("<%= prop.Name %>") </code>.Value %> ' load child objects .NextResult() <%= From child In mObjectData.Children Select _ <code> m<%= child.Name %> = <%= child.Name %> .Get<%= child.Name %> (dr) </code>.Value %> End With End Using End Using End Using End Sub</code>.Value
This is .NET code, which you can see because the template output is inside a .NET function named MemberDataPortalFetch which returns a string constructed with XML literals. By offsetting with XML literals, the code of the function is easily seen – it’s in gray. All of the gray code will be in the output, none of the yellow, blue or black code will be in the output, although it will certainly affect the output.
Where replacements are necessary, XML literals have “embedded expressions” which I have the habit of calling “expression holes.” I’ll talk in another post about what mObjectDatais, but an embedded expression can contain whatever expression you need. An expression is something that returns a value within a single line. So, you can call methods and properties, but you can’t call a subroutine.
Embedded expressions can contain LINQ as shown in the third embedded expression. Here we want to add parameters for all the primary keys. Within the LINQ Select clause, I can use any string. Including the nested code block creates a more readable template and consistency, among other things.
A quick glance may leave you thinking that this is just a variation of the ASP.NET style template syntax used by CodeSmith, CodeBreeze, MyGeneration and others. However, it’s quite different. To begin with its organized into members of a template class. Then, the logic is expressed in expressions, not direct template logic. Finally, you can nest back and forth between output text and code to any depth you require. The code blocks within the LINQ statements above contain embedded expressions. These embedded expressions could be further LINQ statements with further code blocks, etc.
I think there are right and wrong ways to build templates with XML literals. I’ll spend the next couple of posts talking about template organization and metadata handling.