Compiling C# to What!?
Compiling C# code into JavaScript may seem foreign, but Script# is a mature technology that is absolutely worth a look. Our team has been using it very happily for about three months. We've found a number of benefits including:
- Consistently working Intellisense
- Better encapsulation
- Simpler Object Orientation
- Easier deployment (Script# compiles multiple files to a single, optionally minified file)
- Safer refactoring
- Simpler unit testing
- Type safety; and
- Design time syntax checking (no more mistyping a variable and accidentally declaring it to the global scope)
To the Command Line
Typically to get going with Script# you:
- Install the Script# Visual Studio plug-in
- File -> New project
- Select "Script Library" and
- Compile to generate JavaScript
How-To
The how-to looks something like this:
- Download and install Script#
- Add a Class Library (not a Script# project)
- Project properties -> Build -> Advanced -> "Do not reference mscorlib"
- Ideally move the Script# files (C:\Program Files (x86)\ScriptSharp) locally to the solution and check them into source control to a Libs or something similar
- Remove all references, but add: ScriptSharp.dll, ScriptSharp.Web.dll, Script.Jquery
- Edit your .csproj to manually reference Script#'s mscorlib (right click, Unload project, Edit MyProject.csproj)
<Reference Include="mscorlib, Version=0.7.0.0, Culture=neutral, PublicKeyToken=8fc0e3af5abcb6c4, processorArchitecture=MSIL">
<SpecificVersion>True</SpecificVersion>
<HintPath>..\Libs\ScriptSharp\v1.0\mscorlib.dll</HintPath>
</Reference> - Modify AssemblyInfo.cs and remove the following lines:
[assembly: ComVisible(false)]
[assembly: Guid("b5e2449f-193c-46d1-9023-9143618d8491")]
- Modify AssemblyInfo.cs and add the following:
[assembly: ScriptAssembly("ScriptSharpDemoAssembly")]
- Ensure it compiles in Visual Studio
- Create a batch script or PowerShell script that compiles using ssc.exe like this:
..\Libs\ScriptSharp\v1.0\ssc.exe ^
/debug ^
/out:MyScriptSharp.js ^
/ref:"..\Libs\ScriptSharp\v1.0\Framework\mscorlib.dll" ^
.\Properties\AssemblyInfo.cs ^
.\Class1.cs
Now for completeness if you put a simple static method in Class1.cs, something like this:
namespace MyScriptSharp
{
public class Class1
{
public static string HelloWorld()
{
return "Hello World!";
}
}
}
Then run the batch file you should get something like this:
Type.registerNamespace('MyScriptSharp');
////////////////////////////////////////////////////////////////////////////////
// MyScriptSharp.Class1
MyScriptSharp.Class1 = function MyScriptSharp_Class1() {
}
MyScriptSharp.Class1.helloWorld = function MyScriptSharp_Class1$helloWorld() {
return 'Hello World!';
}
MyScriptSharp.Class1.registerClass('MyScriptSharp.Class1');
Obviously you could get these results faster with approach #1. But now you have a lot more control.
Summary
The main downside to this approach is maintaining the batch file is a bit of a hassle. But the upsides are that you can include any file from your server-side C# code. And any changes in that server-side code are automatically reflected in your JavaScript. And any breaking changes in your server-side code generate compile time errors in your client side code. And furthermore none of your team members need to install Script#. For our team it's an easy tradeoff. What about for yours? Please share your thoughts in the comments or on twitter.