While programming in C# using Visual Studio 2008, I often wish for "automatic" code generation. If possible, I'd like to achieve it by making my MSBuild solution file call out to Rake, which would call Ruby code for the code generation, having the resulting generated files automatically appear in my solution.
Here's one business example (of many possible examples I could name) where this kind of automatic code generation would be helpful. In a recent project I had an interface with some properties that contained dollar amounts. I wanted a second interface and a third interface that had the same properties as the first interface, except they were "qualified" with a business unit name. Something like this:
public interface IQuarterlyResults
{
double TotalRevenue { get; set; }
double NetProfit { get; set; }
}
public interface IConsumerQuarterlyResults
{
double ConsumerTotalRevenue { get; set; }
double ConsumerNetProfit { get; set; }
}
public interface ICorporateQuarterResults
{
double CorporateTotalRevenue { get; set; }
double CorporateNetProfit { get; set; }
}
In this example, there is a "Consumer Business Unit" and a "Corporate Business Unit". Every property on IQuarterlyResults becomes a property called "Corporate" + [property name] on ICorporateQuarterlyResults, and likewise for IConsumerQuarterlyResults.
Why make interfaces for these, rather than merely having an instance of IQuarterlyResults for Consumer and another instance for Corporate? Because, when working with the calculator object I was building, the user had to deal with 100's of properties, and it is much less confusing if he can deal with "fully qualified" property names such as "ConsumerNetProfit".
But let's not get bogged down in this example. It is only an example and not the main question.
The main question is this: I love using Ruby and ERB for code generation, and I love using Rake to manage dependencies between tasks. To solve the problem above, what I'd like to do is have MSBuild call out to Rake, and have Rake / Ruby read the list of properties on the "core" interface and then generate the code to make all the dependent interfaces and their properties. This would get triggered every time I do a build, because I'd put it into the MSBuild file for the VS.NET solution.
Has anyone tried anything like this? How did it work out for you? What insights can you share about pros, cons, tips for success, etc.?
Thanks!
We did it with Nant/ruby+ERB - it generates a tone of CRUD in our DAL and data entry form input for our web app. for us it works really well, but there was a good amount of setup time in the beginning that made my boss/customer nervous becuase they figured we should be showing more production than prototype.
Also be sure what the generation is doing - there are differences between generate & modify and generate + integrate. generate & modify is more like using a wizard and is one off. when you generate + integrate you need to understand where/how you will exploit the generated code either through inheritance or through library calls from hand written code into the generated code.
Ruby/erb is not fast executing. A method to determine when you do/dont have to generate are helpful becuase compile cycles start to become long and unproductive. We also found it helpful to always build a small test case to generate even a single set of artifacts before integrating it into the work flow - you have a test of the product and it doesnt slow down anyone while you work on the cg element(s).
I would read Jack Herringtons Code Generation in Action as its geared toward
Ruby. Its got me into CG.
I would also rea Kathleen Dollards Code Generation in Microsoft .NET. It built for using XSLT but the principles are the same for developing the metdadata, transformation and integration stages. Her articles are also helpful that you find in magazines and around the web.
I use rake to generate configuration files that are templated using ERB. The thing to do is edit your project file to insert a BeforeBuild Target that calls rake, similar to:
<Target Name="BeforeBuild">
<Exec Command="rake name_of_my_template_processing_task" />
</Target>
See msbuild exec task docs and a blog post on pre-build events. You need in the Command attribute to:
- supply the path to rake if it's not in the path environment variable already
- set the working directory attribute if you need it to run from a particular directory
- supply a -r argument and the path to the rakefile if you're not executing rake from the directory your project is in.
I wanted to just throw this out there (though I doubt it will be an answer to the question, it should be go information), but there are a couple of good CodeGen tools that have some pretty strong Visual Studio integration that can do much of what you want. Obviously you are looking for a Ruby tool, but for those out there who are not comfortable with Ruby, consider some of the other tools: