Thursday, March 26, 2009

The process of building a Code Generation template

More often than not, you’ll have several related classes and you’ll want to turn them into generated code. There is a process I like to use to make a generation template that’s based on this idea. You can also use the process even if you don’t have the classes, by building them manually.

First, you’ll need a class. For example, we’re going to use generation to create a strongly type representation of a directory structure and files on disk. In the example, these files will be configuration files spread throughout a few directories, but we’ll open them as simple strings to make the sample easier. Let’s look at the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace MyCompany.MyProduct
{
class Configuration
{
private string baseDir = "Configuration";

public Configuration(string baseDir)
{
this.baseDir = string.Concat(baseDir, "\\Configuration");
}

public Network Network
{
get
{
return new Network(baseDir);
}
}
}

class Network
{
private string baseDir;

public Network(string baseDir)
{
this.baseDir = string.Concat(baseDir, "\\Network");
}

public string ProxiesConfig
{
get
{
return File.ReadAllText(string.Concat(baseDir, "\\Proxies.Config");
}
set
{
File.WriteAllText(string.Concat(baseDir, "\\Proxies.Config"), value);
}
}

public string HostsConfig
{
get
{
return File.ReadAllText(string.Concat(baseDir, "\\Hosts.Config");
}
set
{
File.WriteAllText(string.Concat(baseDir, "\\Hosts.Config"), value);
}
}
}

class Security
{
private string baseDir;

public Security(string baseDir)
{
this.baseDir = string.Concat(baseDir, "\\Security");
}

public string RolesConfig
{
get
{
return File.ReadAllText(string.Concat(baseDir, "\\Roles.Config");
}
set
{
File.WriteAllText(string.Concat(baseDir, "\\Roles.Config"), value);
}
}
}
}


Notice that this code already has a “generated” look and feel. The idea is to create a Configuration object with the base path for configuration, and to go down from there to all the configuration items. Network and Security will be directories within Configuration, and the other properties will refer to files in the directories. Notice also that at this point it’s not very important to have complete classes. A rough layout is enough.



The next step is to find varying parts. This is really simple: variables will generally be present as constants or as variable properties. Constants is far more common. In this step, we’ll replace the constants with representative code blocks:



    class Configuration
{
private string baseDir = <#= baseDirectoryName #>;

public Configuration(string baseDir)
{
this.baseDir = string.Concat(baseDir, “<#= baseDirectoryPath #>”);
}

public Network Network
{
get
{
return new Network(baseDir);
}
}
}

class Network
{
private string baseDir;

public Network(string baseDir)
{
this.baseDir = string.Concat(baseDir, “<#= baseDirectoryPath #>”);
}

public string ProxiesConfig
{
get
{
return File.ReadAllText(string.Concat(baseDir, “<#= configFileName #>”);
}
set
{
File.WriteAllText(string.Concat(baseDir, “<#= configFileName #>”), value);
}
}

public string HostsConfig
{
get
{
return File.ReadAllText(string.Concat(baseDir, “<#= configFileName #>”);
}
set
{
File.WriteAllText(string.Concat(baseDir, “<#= configFileName #>”), value);
}
}
}


Then we’ll also replace the varying property names (and class and method names if necessary) with code blocks too:



    class <#= baseDirectoryName #>
{
private string baseDir = <#= baseDirectoryName #>;

public Configuration(string baseDir)
{
this.baseDir = string.Concat(baseDir, “<#= baseDirectoryPath #>”);
}

public <#= childDirectoryName #> <#= childDirectoryName #>
{
get
{
return new <#= childDirectoryName #>(baseDir);
}
}
}

class <#= baseDirectoryName #>
{
private string baseDir;

public <#= baseDirectoryName #>(string baseDir)
{
this.baseDir = string.Concat(baseDir, “<#= baseDirectoryName #>”);
}

public string <#= configFileName #>
{
get
{
return File.ReadAllText(string.Concat(baseDir, “<#= configFileName #>”);
}
set
{
File.WriteAllText(string.Concat(baseDir, “<#= configFileName #>”), value);
}
}

public string <#= configFileName #>
{
get
{
return File.ReadAllText(string.Concat(baseDir, “<#= configFileName #>”);
}
set
{
File.WriteAllText(string.Concat(baseDir, “<#= configFileName #>”), value);
}
}
}


At this point, you should have some duplication. The next step is to remove that duplication by looping through duplicated constructs:



<#
for (int classes = 0; classes < n; classes++)
{
#>
class <#= baseDirectoryName #>
{
private string baseDir;

public <#= baseDirectoryName #>(string baseDir)
{
this.baseDir = string.Concat(baseDir, “<#= baseDirectoryName #>”);
}

<#
for (int props = 0; props < n; props++)
{
#>
public string <#= configFileName #>
{
get
{
return File.ReadAllText(string.Concat(baseDir, “<#= configFileName #>”);
}
set
{
File.WriteAllText(string.Concat(baseDir, “<#= configFileName #>”), value);
}
}
<#
}
#>
}
<#
}
#>


You should also add whatever’s left behind (in this case, the “directory” properties:



<#
for (int classes = 0; classes < n; classes++)
{
#>
class <#= baseDirectoryName #>
{
private string baseDir;

public <#= baseDirectoryName #>(string baseDir)
{
this.baseDir = string.Concat(baseDir, “<#= baseDirectoryName #>”);
}

<#
for (int childClasses = 0; childClasses < n; childClasses++)
{
#>
public <#= childDirectoryName #> <#= childDirectoryName #>
{
get
{
return new <#= childDirectoryName #>(baseDir);
}
}
<#
}
#>
<#
for (int props = 0; props < n; props++)
{
#>
public string <#= configFileName #>
{
get
{
return File.ReadAllText(string.Concat(baseDir, “<#= configFileName #>”);
}
set
{
File.WriteAllText(string.Concat(baseDir, “<#= configFileName #>”), value);
}
}
<#
}
#>
}
<#
}
#>


At this point, you should have a pretty good skeleton. The point now is to make it work:



<#
foreach(string directory in Directory.GetDirectories("myconfigurationdir"))
{
#>
class <#= directory #>
{
private string baseDir;

public <#= directory #>(string baseDir)
{
this.baseDir = string.Concat(baseDir, "<#= directory #>");
}

<#
foreach (string childDirectory in Directory.GetDirectories(directory))
{
#>
public Network <#= childDirectory #>
{
get
{
return new <#= childDirectory #>(baseDir);
}
}
<#
}
#>
<#
foreach (string file in Directory.GetFiles(directory))
{
#>
public string <#= file #>
{
get
{
return File.ReadAllText(string.Concat(baseDir, "<#= file #>");
}
set
{
File.WriteAllText(string.Concat(baseDir, "<#= file #>"), value);
}
}
<#
}
#>
}
<#
}
#>


At this point you should be added any imports that are needed for the generation code to work (System.IO in this case). You may also need to separate processes in methods, as to make them recursive. For instance, our classes need to be generated for each directory in the hierarchy. Finally, you must solve generation-specific problems. For instance, this generation will probably have many invalid class and property names (“Proxies.Config” is not a valid class name). You can change that by using the CleanName procedure that we already reviewed in this blog. The result will look something like this:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

<#
GenerateClass("myconfigdir");
#>
<#+
void GenerateClass(string directoryName)
{
foreach(string directory in Directory.GetDirectories(directoryName))
{
#>
class <#= CleanName(directory) #>
{
private string baseDir;

public <#= CleanName(directory) #>(string baseDir)
{
this.baseDir = string.Concat(baseDir, "<#= directory #>");
}

<#+
foreach (string childDirectory in Directory.GetDirectories(directory))
{
#>
public <#= CleanName(childDirectory) #> <#= CleanName(childDirectory) #>
{
get
{
return new <#= CleanName(childDirectory) #>(baseDir);
}
}
<#+
}
#>
<#+
foreach (string file in Directory.GetFiles(directory))
{
#>
public string <#= CleanName(file) #>
{
get
{
return File.ReadAllText(string.Concat(baseDir, "<#= file #>");
}
set
{
File.WriteAllText(string.Concat(baseDir, "<#= file #>"), value);
}
}
<#+
}
#>
}
<#+
GenerateClass(directory);

}
}


string CleanName(string)

{

//some code cleaning here

}
#>


The final step is to separate the code into modules. For instance, you can put the CleanName procedure in an include T4 file to be used as a helper, put the header in a “main” T4 and the methods in generation T4 files, separate the properties into its own include, or whatever feels good to you.



--

Written by Joaquin, joj AT clariusconsulting DOT net. Disclaimer: opinions expressed in this post are my own and not necessarily reflect those of Clarius Consulting.

Monday, March 23, 2009

Visual T4 @ MIX09

We’ve been catching up on web techs watching MIX09 videos and guess what…?

Scott Hanselman in his File|New -> Company: Creating NerdDinner.com with Microsoft ASP.NET Model View Controller (MVC) and Phil Haack in his Microsoft ASP.NET Model View Controller (MVC): Ninja on Fire Black Belt Tips talks both mention the Clarius Visual T4 Editor for editing T4 templates!

Here is a screenshot of Phil, on stage, using the Visual T4 Editor Professional edition:

VisualT4Mix09

Good to see Visual T4 being used everywhere!!

NHibernate: Why override GetHashCode and Equals?

When using NHibernate collections, or when comparing two objects that are configured via NHibernate configuration, NHibernate code will use the Equals and GetHashCode methods in the class. It is very important to implement this methods in a way that will make two different entities return different values and to identical entities return identical values. That’s the only condition. The value doesn’t need to be related to anything in the table at all as long as it passes that test. This is both easy and hard. Let me show you why.

The point here is to always generate a value that will represent a row in the table. In a normal table, any candidate key (that is, a unique index or a primary key) will serve this role. In the samples that come with Visual T4 Editor Professional edition we use the primary key to generate these methods:

        public override int GetHashCode()
{
int hashCode = 0;
hashCode = hashCode ^ CustomerID.GetHashCode();
return hashCode;
}

public override bool Equals(object obj)
{
Customers toCompare = obj as Customers;
if (toCompare == null)
{
return false;
}
if (this.CustomerID != toCompare.CustomerID)
{
return false;
}
return true;
}


The Equals method is fairly simple to override. Just compare keys, and if everything matches return true. GetHashCode is a little different. You must return an integer value tailored to the needs of the two rules. For the sample, we have chosen to use xor to compare, due to a high success rate. For production code, you should choose to “shift and or” or to concatenate and get the hash code of the string. Both methods will give you a 100% success rate, on varying levels of complexity and performance.



There is an additional problem here, specially for code generation: if you have a transient object (that is, one that is not yet saved to the database) and identity value will always be a bad choice. The problem is that until NHibernate saves the object to the database, the value of the identity (or primary key, depending on configuration) will be the default value for the datatype (0 in this case). Hence, two unsaved values will be equal. Although this is technically correct (unsaved values may be considered “null” for some purposes) it is highly impractical.



In this case, the best solution is to take an alternate key (an unique non-null key) and use that for the comparison. As long as the user actually fills that value when constructing the object, everything should be fine. A code generator may find a candidate key and use it. It will not, however, be able to know if this candidate key will be filled when needed. As a default solution both primary key and a candidate key may work. As a definitive solution, you should use the class knowing that you may run into this issue and manually override (as explained in Extending Code Generation with Partial Classes and Inheritance) when needed. To be 100% sure, you should always create the GetHashCode manually, and override equals with this:



        public override bool Equals(object obj)
{
Customers toCompare = obj as Customers;
if (toCompare == null)
{
return false;
}
return (this.GetHashCode() != toCompare.GetHashCode())
}


--

Written by Joaquin, joj AT clariusconsulting DOT net. Disclaimer: opinions expressed in this post are my own and not necessarily reflect those of Clarius Consulting.

Transforming Type Names

There are many situations in code generation where you may need to render the name of a Type in the generated file. For instance, you may have a method somewhere that translates a data type in a specific format to a Type, and then you want to render that type. The easy way to do it is obviously
    Type.ToString() 

but this has many drawbacks. The first problem, and this is mostly aesthetic, is that standard types like “int”, “long”, “double”, etc will be rendered as “System.Int32”, “System.Int64”, “System.Double”. Although this will work, the resulting code will have a “generated” look and feel. Your code should always be as “not-generated” as possible. That will make it easier to read and debug.

The second problem is that there are types that will simply not translate to your preferred language easily. For instance, “List<string>” will be translated as “System.Collections.Generic.List’1[System.String]”. There is no way for that text to be useful in a generation context!

There are a few ways to work around this. You may code a few methods that will translate from the Type to your language. This is not a trivial task, but there are a few implementations readily available. For instance, the class ContractNameServices.cs in MEF (http://www.codeplex.com/MEF/SourceControl/changeset/view/26383#370431) has a method named GetDefaultContractName which does just that, and it is very cleanly implemented.

The easiest way is to use a CodeDomProvider for your language. The following few lines of code illustrate this concept:
CodeTypeReferenceExpression type = new CodeTypeReferenceExpression(typeof(System.Collections.Generic.List<float>));
CodeDomProvider csProvider = Microsoft.CSharp.CSharpCodeProvider.CreateProvider("C#");
CodeDomProvider vbProvider = Microsoft.VisualBasic.VBCodeProvider.CreateProvider("VB");
StringWriter writer = new StringWriter();
csProvider.GenerateCodeFromExpression(type, writer, new CodeGeneratorOptions());
writer.Write(writer.NewLine);
vbProvider.GenerateCodeFromExpression(type, writer, new CodeGeneratorOptions());
Console.WriteLine(writer.ToString());


The output of this code will be:
System.Collections.Generic.List<float>
System.Collections.Generic.List(Of Single)


which is both useful and language independent at the same time.

--

Written by Joaquin, joj AT clariusconsulting DOT net. Disclaimer: opinions expressed in this post are my own and not necessarily reflect those of Clarius Consulting.

Wednesday, March 18, 2009

Visual Web Developer Team @ MS highly highly recommends Visual T4 Editor

We really love each time we see our Visual T4 products used inside Microsoft.

The Visual Web Developer Team in  T4 Templates: A Quick-Start Guide for ASP.NET MVC Developers says:

If you open a .tt file inside Visual Studio, you may notice they look a bit flat – like a wall of black text.  We highly highly recommend you download T4 Editor, an add-on to Visual Studio made by Clarius Consulting, to provide you with syntax highlighting and some basic T4 statement completion.  They have a free version called the ‘Community Edition’, as well as a much more powerful ‘Professional Edition’ – check out the feature comparison if you are interested.  This add-on really makes a big difference in template authoring, as you can see below.

While the bigger font size and strident red-on-yellow colors are ours the ‘highly highly’ is theirs :-)

Monday, March 9, 2009

Where did my Visual T4 IntelliSense go?


If you're using Refactor! or Resharper you will notice that the IntelliSense provided by the Visual T4 Editor for embedded C# code blocks doesn’t work as expected.

The reason for this is the above mentioned tools replace the built-in Visual Studio C# IntelliSense and provide their custom ones.

This doesn’t play well with any other tool expecting the built-in IntelliSense to be there, as it is the case for our Visual T4 Editor and the built-in ASP.NET editor which won’t also behave well if you have any of the two refactoring tools installed.

The cure? Download and install this patch.

Then: open Visual Studio and go to Tools -> Options, open the tree at Text Editor\T4 Editor\Miscellaneous and check the Intellisense replacement item.

This is a new experimental feature that tries to mitigate Refactor! and Resharper “hacky manners” of replacing the built-in IntelliSense and will get back to normal the IntelliSense support while editing a C# embedded code block in a T4 template.

We’ve also detected that these refactoring tools don’t do a great job of restoring previous settings after uninstalling them, so it may be the case that you once used them but you currently don’t have any of them installed and you still don’t get proper IntelliSense. This can be fixed this way: go to Tools –> Options, browse the tree at Text Editor\C#\General and make sure Auto list members is checked.

We want to thank all of our customers that are also Refactor! or Reshaper customers and have reported this, you can all now enjoy the fix!.

Wednesday, March 4, 2009

Now supporting ASP.NET MVC code generation!

UPDATE: added correct download link

After teasing you a bit here we took a couple of weeks to test this and have now added support for nice integration between the ASP.NET MVC bits and our Visual T4 Editor.

If you are an existing customer who bought your copy before 03/03/09 you can download for free the patch to add support for this (and a few more other goodies) from here.

If you buy the Visual T4 Editor today, you will get this support right into the box, without having to install anything else.

As you can see, we do care for keeping our Visual T4 products updated up-to-the-minute to support all the new stuff that will be coming out from Microsoft and other companies regarding T4 adoption.

Sunday, March 1, 2009

NHibernate configuration: Xml, Fluent or Attributes

When using NHibernate, you need to map tables to objects. Without this mapping, there is no way to reconcile the two models. The mapping can be done in three very different ways: Attributes, Xml or Fluent syntax. Each model has its pros and cons. Let’s review them one by one.

Fluent

This is the newest way of doing OR/M in NHibernate. It works by providing a constructor that will establish the mappings using a Map() method, and by inheriting from a NHibernate provided class, like this:
public CustomerMap : ClassMap<Customer>  
{
public CustomerMap()
{
Id(x => x.ID);
Map(x => x.FirstName);
Map(x => x.LastName);
HasMany<Address>(x => x.Addresses)
.AsBag();
}
}


You can find more information about this type of mapping in James Gregory’s blog.

Fluent mapping is cool, and it’s the newest way of mapping. This way of mapping is not officially supported, and it doesn’t cover every possible mapping, but it’s type safe (as it’s fluent), it’s really simple and it doesn’t use Xml. Also, since the mapping class is outside of the “Model” class, the model integrity is preserved.

Attributes

Attributes are also a very effective way of mapping without using Xml. When you use attributes, NHibernate creates the Xml for you on runtime. That is, you may not be using the xml config files, but the files are being generated and used anyway. Attributes are used like this:



[NHibernate.Mapping.Attributes.Class]    
public class Customer
{
[NHibernate.Mapping.Attributes.Id(0, TypeType=typeof(int))]
public int ID;
[NHibernate.Mapping.Attributes.Property]
public string FirstName;
[NHibernate.Mapping.Attributes.Property]
public string LastName;
}


The cool thing about attributes is that you don’t violate the DRY principle. You do violate it (a lot) when using xml files. The bad thing about attributes is that they are all over your model. That pushes NHibernate all over the place instead of leaving it in your persistance layer (where it should be). Also, the attributes require a certain order, which is counterintuitive to the way attributes are generally used.

Xml

Xml is the standard format for configuration. It looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="MyNamespace" assembly="MyAssembly">

<class name="Customer" table="Customers">
<id name="ID">
<generator class="identity" />
</id>

<property name="FirstName" />
<property name="LastName" />

<bag name="Addresses" table="Addresses">
<key column="CustomerID"/>
<one-to-many class="MyNamespace.Address, MyNamespace"/>
</bag>
</class>
</hibernate-mapping>


This format is slightly more complex than the others, and it’s inherently not safe as it’s Xml and not code. It also forces you to repeat information already stated (class names, property names, etc). On the other hand, it’s completely transparent to your code, allowing you to take NHibernate out of the picture at any time, or adding it with no changes to your model.

How this affects code generation

If you’re generating your DAL using T4, your perspective on some of these issues may change a little. First, even though DRY is an important principle, it isn’t as important in code generation. You’re not repeating yourself, the generated code is. There’s a difference there: only one set to maintain (not two), and if the code is being regenerated in each build, then there’s nothing to maintain. That eliminates the main advantage of using attributes.

Also, type safety isn’t that important because in generated code you’re not actually writing the code. Compile time safety is cool, but if your code is being properly generated you don’t have a big error-prone surface in the configuration. That eliminates the main advantage of using Fluent configuration.

In code generated code, I always try to make the code as close as possible as code I would have written by hand. That is, no weird names, standard data types, regular patterns. Both Fluent (to a lesser extent) and Attributes provide a very strong binding to NHibernate. Also, Fluent is not (yet) fully functional and fully supported. Xml is still ugly, but it’s being generated automatically and it shouldn’t be modified by the developer.

That’s why in the context of code generation I prefer to use Xml configuration instead of Attributes or Fluent.

--
Written by Joaquin, joj AT clariusconsulting DOT net. Disclaimer: opinions expressed in this post are my own and not necessarily reflect those of Clarius Consulting.

Visual Studio 2010: we’re getting there.

We’ve received a couple of emails now from (very) early adopters guys asking us if we do have a VS 2010 compatible version of our Visual T4 Editor and Visual T4 Code Generator.

The answer is no, we don’t have one just yet.

The reason is publicly available Visual Studio 2010 CTP bits are not ready yet to support the basics we need to make an early release of our tools.

So, when can you expect our Visual T4 bits running on Visual Studio 2010? We’re working –a lot– on having some early bits that we will make available by when Visual Studio 2010 beta 1 goes out.

And… when is Visual Studio 2010 beta 1 going out? Well, this is a question you should ask to Microsoft! :)