Monday, March 23, 2009

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.

0 comments:

Post a Comment