IgorShare Thoughts and Ideas

Consulting and Training

Roslyn: C# is cheating on me with JavaScript (or how to compile C# into JavaScript)

Posted by Igor Moochnick on 08/20/2012

imageWhile working extensively on development of the Single Page Applications (SPA) I was facing a fact that my server-side data models were evolving quicker than their JavaScript counterparts. Both the client-side and the server-side data models were getting quickly out of sync.

The brute force solution of using the T4 templating engine to emit both the client-side and the server side data models didn’t look that appealing to me. Primarily due to a simple fact that it’s not that easy to refactor the T4 templates. And, the ReSharper junkie like me, can’t tolerate this fact.

So I’ve decided to give the latest release of Roslyn compiler-as-a-service CTP another spin and use it as part of my build sequence and compile my C# models directly into the appropriate JavaScript ones. This was giving me the advantage of using the C# as a primary development environment and leaving the JavaScript to follow the “big-brother”.

Jinx C#-to-JavaScript compiler was created as a result of this exercise. You’re welcome to get the Jinx source from the GitHub. I’ll appreciate any collaboration on this project.

Note: all of the code is an intermediate solution that was answering my personal needs for the project I was running. It is in no-way represent the full fledge solution. If you want something bigger and more feature-reach, you can either contribute to my solution or look into projects like Script# or SharpKit.

The workflow, I ended up with, was very simple:

  1. Build a web application
  2. In the web application create C# data models and, those that have to be compiled to JavaScript, mark them with the [JavaScript] attribute (*)
  3. As a post-build step, run the “jinxc” command line compiler to emit the JavaScript data models directly into your Scripts folder

(*) – I’ve decided to use attribute as an option to reduce unnecessary noise from the compilation. The compiler will ignore all of the non-marked classes. This is not a requirement, but an option.

The example, we’re going to discuss here, is a simple To-Do list SPA application (based on the ToDoMvc with Knockout.js) with the Asp.Net WebApi REST service.

The simple C# data model that I needed for the client-server communication looks like this:

[JavaScript]
public class ToDoItem
{
public Guid guid { get; set; }
public string title { get; set; }
public bool completed { get; set; }
}
view raw gistfile1.cs hosted with ❤ by GitHub

The following command compiles the source data model from C# to JavaScript:

#> jinxc [original] [destination]

The compiler creates the following JavaScript data model:

var ToDoItem = function() {
var self = this;
return {
guid: "",
title: "",
completed: false,
};
};
view raw gistfile1.js hosted with ❤ by GitHub

Make sure that the compiler output is generated in the destination folder for all your JavaScript models.

The generated model is very simple (in the current implementation) and represents the RAW structure that you need to fill in before sending it across the wire. JQuery ajax helpers are very handy for that:

this.registerOnServer = function () {
$.post("/api/ToDo", getDataModel());
};
this.removeFromServer = function () {
$.ajax({
type: "DELETE",
url: "/api/ToDo/" + self.guid
});
};
this.updateOnServer = function() {
$.ajax({
type: "PUT",
url: "/api/ToDo/" + self.guid,
data: getDataModel()
});
};
function getDataModel() {
var item = new ToDoItem();
item.guid = self.guid;
item.title = self.title();
item.completed = self.completed();
return item;
}
view raw gistfile1.js hosted with ❤ by GitHub

As you can see, the usage of the Jinx compiler is straight forward, but the underlying “magic” is not that simple. Main task is handled by Roslyn itself – it parses the source C# and generates a full AST (abstract syntax tree).

There are 2 main ways to traverse the tree:

  1. Use the SyntaxWalker helper class – override only the handlers of interest (i.e. “override void VisitVariableDeclaration” will be called ONLY when a variable declaration is visited)
  2. navigate through all of the nodes and their properties by accessing the AST nodes directly

The Jinx implementation uses both techniques to achieve its goals: first one – to jump directly to the points of interest and the second one to interrogate the context in details.

To build the Jinx compiler you’ll need the following Prerequisites:

  1. VS 2012
  2. VS 2012 SDK
  3. Roslyn June 2012 CTP (more info)

I’ll be writing more about Roslyn in general and Jinx in particular. So stay tuned …

3 Responses to “Roslyn: C# is cheating on me with JavaScript (or how to compile C# into JavaScript)”

  1. zproxy said

    Interesting. Have you tried jsc-solutions.net yet? We have WebGL support – http://www.youtube.com/watch?v=KzR6KVU3dik 😉

  2. […] compiler as a service project lets you copy and paste VB code as C# and vice versa, and is already also being used to compile C# as JavaScript. Microsoft’s Anders Hejlsberg is rumoured to be working on a […]

Leave a comment