4.1 Code generator for C#

Having walked through the general code generation structure and operation back in Section 3.3, our focus in this chapter will be on code generation topics specific to C#. These include the generation of the test environment user interface implementation, the creation of the project file to be used with MSBuild, and the compilation and execution of the generated code.

As we have already seen in Section 3.3, part of the UI generation has already been taken care of by the ‘_Cs_Display’ subgenerator, which produces the generic definitions of buttons, icons and time zone slots. In addition to these, a physical implementation for the UI is still needed. Therefore, the required xaml and xaml.cs files are generated for the test environment main window and for each watch model. An example of the xaml file for the Ace model is shown in Listing 1 and its xaml.cs counterpart in Listing 2 (these files were produced by ‘_Cs_WatchModel_Xaml_for_Windows’ and ‘_Cs_WatchModel_Xaml_cs’ sub-generators).


<src:AbstractWatchWindow x:Class="Digital_watch.Ace"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:src="clr-namespace:Digital_watch"
  xmlns:local="clr-namespace:Digital_watch"
  Title="Ace" Height="300" Width="300">
  <Grid>
    <local:WatchCanvas x:Name="WatchCanv" />
  </Grid>
</src:AbstractWatchWindow>

Listing 1. Generated UI xaml code


public partial class Ace : AbstractWatchWindow
{
  public Ace() : base()
  {
    InitializeComponent();

    master=new Master();
    master.init(new DisplayX334(), new TASTW(master));

    WatchCanv.init(master,
      this.getType().ToString().Split('.').Last<String>(),
      nameLabels, zoneLabels, iconLabels);
  }
}

Listing 2. Generated UI .xaml.cs code

The generated C# code above defines the watch model as an extension of the AbstractWatchWindow and adds the initialization for the new class. WatchCanv is a Windows Presentation Foundation (WPF) user control which defines the layout of the Watch UI.

To enable the build process with MSBuild, the C# generator also produces MSBuild project files. To work properly, the build process needs a predefined folder structure and project files that contain the necessary information for building and running the generated code. The folder structure is created in the ‘_prebuild for C#’ sub-generator.

Every MSBuild project has one solution file and one project file. The solution file (.sln extension) contains the project name, globally unique ids (guid) for the solution and target platform definitions. The project file (.csproj extension) contains a lot of default information which is not explored here further. The critical parts are the <Itemgroup> sections that hold information about references needed by the project and the filenames that are included in the build process. A partial example of a generated project file showing the three types of tags that are needed for including the generated files to the application is shown in Listing 3.
01 <ItemGroup>
02   <ApplicationDefinition Include="App.xaml">
03     <Generator>MSBuild:Compile</Generator>
04     <SubType>Designer</SubType>
05   </ApplicationDefinition>
06   <Compile Include="Result.cs" />
07   <Compile Include="Simple.cs" />
08   <Compile Include="Delicia.xaml.cs">
09     <DependentUpon>Delicia.xaml</DependentUpon>
10   </Compile>
11   <Page Include="Ace.xaml">
12     <Generator>MSBuild:Compile</Generator>
13     <SubType>Designer</SubType>
14   </Page>
15   <Page Include="WatchCanvas.xaml">
16     <Generator>MSBuild:Compile</Generator>
17     <SubType>Designer</SubType>
18   </Page>
19 </ItemGroup>

Listing 3. Part of C# project file.

Every WPF application has files named App.xaml and App.xaml.cs that define the application starting point, specified by the <ApplicationDefinition> tag in the listing above (line 2). After that every .cs file is included in <Compile Include> tag (lines 6-7). The .xaml.cs files also have a <DependentUpon> tag inside them defining the dependent .xaml file (line 8). And lastly every .xaml file (except App.xaml) gets its own <Page Include> tag (lines 11-18).

With the UI definitions and application initialization in place, the C# code generation is completed with the creation of a batch file called vs.bat that manages the actual building and execution of the generated code. While it may sound quite simple, this task is actually rather complex, because of the variety of versions we want to support. In the basic scenario the batch file will first check the presence and resolve the version of the .NET framework to be used. If the framework is found, the code will be compiled with MSBuild. If the project compiles successfully, the compiled WatchModels.exe will be launched.