|
Hi All,
I threw something quick and dirty together to generate Typescript interface files from C# POCOs. I used a Razor template and the Razor Engine project as the basis of the code generator: http://razorengine.codeplex.com/
This is basically programming 101 and I know a real code generator could be better but here it is... it's enough to do what I need (for passing POCOs between client and server) and I can add types as I move along to the switch statement in the
template:
Usage:
new TypeScriptGenerator().Generate(
model:
new TypeScriptGeneratorModel()
{
// C# Types you want to output as TypeScript Interfaces
Types = new List<Type>()
{
typeof(Programmer),
typeof(ProgrammingLanguage)
}
},
templatePath: @"c:\yourpath\TypeSciptInterfaceTemplate.cshtml",
outputFile: @"c:\yourpath\GeneratedTypes.d.ts");
Generator:
public class TypeScriptGeneratorModel
{
public List<Type> Types { get; set; }
}
public class TypeScriptGenerator
{
public void Generate(TypeScriptGeneratorModel model, string templatePath, string outputFile)
{
var template = System.IO.File.ReadAllText(templatePath, Encoding.Default);
var rendered = Razor.Parse(template, model);
System.IO.File.WriteAllText(outputFile, rendered);
}
}
Razor Template (a few loops and a big old switch that can be modified to taste):
@model TypeScriptGeneratorModel
/* Generated at @DateTime.Now */
@functions{
string getTypesScriptType(string propertyType)
{
switch (propertyType)
{
case "System.String":
return "string";
break;
case "System.Int32":
return "number";
break;
case "System.Boolean":
return "bool";
break;
case "System.Nullable`1[System.Boolean]":
return "bool";
break;
case "System.Nullable`1[System.Int32]":
return "number";
break;
default:
break;
}
return null;
}
}
@foreach (var t in Model.Types)
{
<text>interface</text> @t.Name @("{")
<text>
</text> // force a line break
foreach (var p in t.GetProperties())
{
var typeString = getTypesScriptType(p.PropertyType.ToString());
if (typeString == null)
{
<text>//@p.Name: of type @p.PropertyType does not have a corresponding typescript type mapping yet</text>
}
else
{
if (p.PropertyType.ToString().Contains("Nullable"))
{
@(string.Format("{0}?: {1}; // {2}", p.Name, typeString, p.PropertyType))
}
else
{
@(string.Format("{0}: {1}; // {2}", p.Name, typeString, p.PropertyType))
}
<text>
</text> // force a line break
}
}
@("}")<text>// @t.Name</text>
<text>
</text> // force a line break
}
Example Entities/POCOs and Example Output
I will just extend the case statement above as needed to add my own types. The generator will put comments in for types it doesn't know yet. Here are some examples, with some known property types and other unknown property types.
public class Programmer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<ProgrammingLanguage> Languages { get; set; }
public bool HasUsedTypeScript { get; set; }
}
public class ProgrammingLanguage
{
public string Name { get; set; }
public int? Version { get; set; }
}
Output - notice "Languages" is an unknown type, I can just add to the switch statement as needed
/* Generated at 12/13/2012 1:11:50 PM */
interface Programmer{
FirstName: string; // System.String
LastName: string; // System.String
//Languages: of type System.Collections.Generic.List`1[CoreWebSite.Tests.Generator.ProgrammingLanguage] does not have a corresponding typescript type mapping yet
HasUsedTypeScript: bool; // System.Boolean
}// Programmer
interface ProgrammingLanguage{
Name: string; // System.String
Version?: number; // System.Nullable`1[System.Int32]
}// ProgrammingLanguage
That's all! Good enough for me for now. Maybe it will be a jump start for anyone here before a real generator comes out :)
Jon
P.S. Use at your own risk I literally wrote this in an hour. Cheers
|