Introduction
After using a number of open source and commercial trial code generators I was not entirely happy with any particular solution. The following article provides a framework for creating your own code generator and details how it works.
- Features of the IDE. For example:
- Source Control Integration
- Intellisense
- Integration with existing projects and solutions
- The ability to set parameters that can be used when generating output
Create an ASP.NET Website
The code generators will be created within an ASP.NET website (as opposed to a web application). This gives us the advantage of publishing a precompiled website where no ASPX or code file source code is visible. The precompiled website can later be obfuscated if required.
Add two user controls to the project and the page called:
ParametersControl
ExecutionControl
The Default.aspx source is shown below:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>
<%@ Register Src="ExecutionControl.ascx" TagName="ExecutionControl"
TagPrefix="uc1" %>
<%@ Register Src="ParametersControl.ascx" TagName="ParametersControl"
TagPrefix="uc2" %>
<uc1:ExecutionControl ID="ExecutionControl" runat="server" />
<uc2:ParametersControl ID="ParametersControl" runat="server" />
Modify the code file so that parameters control only displays if there are no Request.Form items, while execution control only displays if there are Request.Form items.
protected void Page_Load(object sender, EventArgs e)
{
ParametersControl.Visible = (Request.Form.Count == 0);
ExecutionControl.Visible = (Request.Form.Count != 0);
}
ParametersControl
The parameters control is used to provide parameters to the code generator from our host. The parameters control uses HTML controls so that posted data can be accessed directly when generating our output (using Request.Form). The ParametersControl.ascx source is shown below:
<html>
<body>
<form name="ParamForm" runat="server">
Name:
<input name="Name" type="text" style="width: 317px" /><br />
<input name="Submit1" type="submit" value="Execute" />
</form>
</body>
</html>
Note: The parameters control does not contain any code.
ExecutionControl
The execution control is used to perform the code generation. The parameters are accessed using Request.Form. The ExecutionControl.ascx source is shown below:
Your name is: <%=this.Request.Form["Name"]%>
Windows Application Host
It is possible to host the ASP.NET runtime within a Windows Application. The host attached in the sample will provide a list of all ASPX files in the root of the application's physical directory.
When a file is selected, the page will be loaded in a browser control that is embedded within the host application.
When a file performs a postback to the server, the browser request will be intercepted and the call will be made to the ASP.NET runtime.
ASPNETHost Library
When creating an ASP.NET host, a class must be provided as the host type. The Web Application needs to include a reference to the library that contains this class. The source to create the ASP.NET host is shown below:
using System.Web;
public static ASPNETHost CreateASPNETHost(string physicalRoot)
{
return (ASPNETHost)Hosting.ApplicationHost.CreateApplicationHost(
typeof(ASPNETHost), "/", physicalRoot);
}
The source code below illustrates how to capture the output of a page from the ASP.NET runtime:
StringWriter sw = new StringWriter();
HostWorkerRequest swr = new HostWorkerRequest(webPage, query, postData, sw);
HttpRuntime.ProcessRequest(swr);
return sw.ToString();
If required, we can also execute the generator without visiting the parameter page by manually creating the post data for submission. The source code to do this is shown below:
public string ProcessGenerator(string generatorName,
Dictionary<string, string> settings)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (KeyValuePair<string, string> kvp in settings)
{
if (sb.Length != 0)
{
sb.Append("&");
}
sb.Append(System.Web.HttpUtility.UrlEncode(kvp.Key));
sb.Append("=");
sb.Append(System.Web.HttpUtility.UrlEncode(kvp.Value));
}
byte[] postData = System.Text.Encoding.ASCII.GetBytes(sb.ToString());
return GetPage(generatorName + ".aspx", null, postData);
}
Summary
To conclude, the source code attached should provide the basis for a framework for performing code generation without the use of a 3rd party tool. In addition, we get all the benefits of Visual Studio (source control, intellisense, help, etc). Some things to consider:
- You can create custom ASP.NET controls to render output as required within your generator.
- You may wish to parse the generated output to perform additional processing. For example: Split output into multiple files
Acknowledgements