One of the biggest issues a developer faces when developing a large application, is maintaining design standards and methods. Design documents, coding standards, and code review were the only tools a developer had to work with in the golden days of coding. With the birth of code generators such as CodeSmith, development teams are now armed with a powerful tool to expedite the development process and maintain a standard throughout the application. When developing applications, templates can save you a lot of time by using common design patterns for generating different business objects. By definition, templates are repeatable patterns, which can be derived from any design methods. The benefit of using templates in code generation is the ability to enforce design methods and standards while saving development costs for any application. This article will present a basic design pattern and the templates to generate code for the design pattern.
Business objects contain properties that reflect data; you will find objects named invoice, invoice detail, etc. Commonly, they include embedded relationships -- for example, an invoice object may have a property that retrieves the details for that invoice instance.
Based on this simple observation, we can develop a design standard for our business objects:
The Business Object Class Template (ClassGenerator.cst) is used to create a business object�s properties and methods. A standard set of methods for accessing the object's data will be generated for each object defined in an XML document. The following methods will be created for each business object defined:
CreateNewObject
Object
DeleteObject
Copy
Delete
Fetch
Save
Update
The Business Object Collections Template (CollectionGenerator.cst) is used to create a collection class for each business object. The collection object uses the 'CollectionBase' as the base class. The following methods will be created for each business object defined:
CollectionBase
ObjectCollection
Count
Item
Add
Contains
IndexOf
Insert
Remove
OnInsert
OnRemove
OnSet
OnValidate
The Business Object Data Class Template (DataClassGenerator.cst) is used to define the data access layer for each business object. The following methods will be created for each business object defined:
ObjectData
FetchObject
UpdateObject
The Business Object Base Class Template (BaseObjectClass.cst) is used to create the base class for each business object. The following are the properties used for each business object:
Id
Name
GenerateObjectId
The Business Object Base Data Class Template (BaseDataClass.cst) is used to create the base class for each business object. The following are the properties used for each business object:
BaseDataClass
ConnectionString
AddParamToSQLCmd
SqlCommand
ExecuteCollectionReader
ExecuteObjectReader
ExecuteReaderCmd
ExecuteScalarCmd
SetCommandType
CommandText
The Data Layer Template (DataGenerator.cst) is used to create the required database objects needed to support the business objects.
Object_Create
Object_Delete
Object_Fetch
Object_Update
Based on a definition provided by an XML Document, the generator will produce code for your business object, business object collection, business object data access, business object tables, and stored procedures.
attribute
maps to
remarks
class
table
name will represent the table name
property
column
name will represent the column name
name
represents the table name
represents the column name
type
represents a system type or a business object collection
maxSize
C# Type
Maps to SQL type
string
nvarchar
int
DateTime
smalldatetime
bool
bit
decimal
money
Let's create a simple Invoice Business Object. The invoice object will contain a customer name, invoice date, invoice paid status, and line items. The following XML document defines the objects:
xml version="1.0" encoding="utf-8" ?> <BusinessObjects xmlns="http://www.austinconnergroup.com"> <class name="Invoice"> <properties> <property name="Id" type="String" maxSize="36" /> <property name="Customer" type="String" maxSize="96" /> <property name="InvoiceDate" type="DateTime" maxSize="" /> <property name="InvoicePaid" type="bool" maxSize="" /> <property name="InvoiceDetails" type="InvoiceDetailCollection" maxSize="" /> </properties> </class> <class name="InvoiceDetail"> <properties> <property name="Id" type="String" maxSize="36" /> <property name="InvoiceId" type="String" maxSize="36" /> <property name="LineItem" type="Int" maxSize="" /> <property name="ItemDescription" type="String" maxSize="96" /> <property name="ItemCostPerUnit" type="Single" maxSize="" /> <property name="ItemQuanity" type="Int" maxSize="" /> <property name="ItemUnit" type="String" maxSize="8" /> </properties> </class> </BusinessObjects>
In our definition document, we define two objects, Invoice and InvoiceDetail. You will notice that the Invoice object contains a property InvoiceDetails which is of the type InvoiceDetailCollection. This defines a relationship between InvoiceDetail and Invoice, and will produce the required methods and SQL statements for this relationship.
Invoice
InvoiceDetail
InvoiceDetails
InvoiceDetailCollection
Once we have our model, we are ready to generate our code. BuildTemplate.cst is the main entry point for generating the code for all the business objects, and has the following properties:
XmlFile
OutputDirectory
GenerateBaseClasses
true
RootNamespace
ObjectNamespace
BusinessLogicNamespace
DataAccessNamespace
DeveloperName
CompanyName
The article here presents the prototype that I developed for proof of concept. After writing the generator and supporting templates, I was so amazed at the results, I immediately wrote the templates for our team and deployed them into our production environment. One of the biggest benefits was not the cost savings in time, but the fact that all the generated code was self documenting. This fact alone was worth the efforts in creating these templates. The biggest battle I faced everyday was the lack of documented code, now it's a snap.