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.