Further reading:

CS-Script Overview

CS-Script is one of the most mature C# scripting frameworks available today. CS-Script first public release is dated back to 2004. At that time .NET ecosystem didn't provide any scripting solution. What is even more intriguing is the fact that at that time Microsoft consistently refused any call for such a solution. It insisted that there is no need for scripting as it has no place in .NET domain. Thus CS-Script was a pioneering effort to bring scripting experience to the developers when .NET vendor failed to do so. The main idea of CS-Script is to allow "plain vanilla" C# code execution from both command-prompt and form any CLR application hosting the script engine.

Things have changed since then. Today Microsoft is behind the ongoing Roslyn effort - their own compiler-as-service solution. Mono also has their compiler-as-service (Mono.CSharp) released around 2010. Though CS-Script remains one of the best choices of scripting platform due to the unorthodox conceptual approaches and unique features not found in other solutions.

What makes CS-Script almost unique is the comprehensive approach to scripting as a software development technique that has various applications (beyond just simple "eval"). CS-Script was hugely influenced by Python. In fact many CS-Scrip features was 'borrowed' from Python: referencing external scripts and assemblies, caching, converting scripts into self-sufficient executables. Thus having Python in mind CS-Script provided the answer for both standalone (script file) execution by the script engine executable and hosted script (file or in-memory text) execution by the script engine hosted by the user application.

For the hosted script execution CS-Script provides one unified interface, which allows switching between underlying compiling services (Mono, Roslyn and CodeDom) without the need to change the hosting code.

CSScript.EvaluatorConfig.Engine = EvaluatorEngine.Roslyn;
                                //EvaluatorEngine.Mono;
                                //EvaluatorEngine.CodeDom;

var sqr = CSScript.Evaluator
                  .CreateDelegate(@"int Sqr(int a)
                                    {
                                        return a * a;
                                    }");

var r = sqr(3);

Standalone script execution

Additional documentation

The simplest way to execute the C# script is to run the script engine executable (css.exe) and pass the script file as a parameter. The script file is a file containing an ordinary ECMA-compliant C# code. CS-Script currently targets Microsoft implementation of CLR (.NET 2.0/3.0/3.5/4.0/4.5) with full support on Mono. CS-Script is implements script caching that ensures that the script file is never compiler unless it has change since the first execution or it is the first execution. This in turn allows a remarkable performance for the script execution, which is identical to the performance of the fully compiled assembly. Thus CS-Script implements JIT compilation but not within the scope of the code fragments (e.g. .NET JIT compilation) but within the scope of whole script file.

Some of the important features of CS-Script are:
  • Including (referencing) dependency scripts from the main script
  • Referencing external assemblies from the script
  • Automatic referencing external assemblies based on analyses of the script imported namaspaces ('usings')
  • Automatic resolving (downloading and referencing) NuGet packages
  • Possibility to plug in external compiling services for supporting alternative script syntax (e.g. VB, C++)
  • Scripts can be executed on Windows, Linux and OS X (last two will require Mono)
  • Full integration with Windows, Visual Studio and Notepad++ (CS-Script extension for Notepad++ brings true Intellisense to the 'peoples editor')
  • ...

You can find all the details about the stand alone script execution in the online documentation.

The default CS-Script distribution includes various components that make scripting a comfortable experience and yet it in may cases a single script engine file is sufficient for the scripting execution.

The most convenient way of installing CS-Script is to get it from Chocolaty (Windows equivalent of Linux apt-get)

Hosted script execution

Additional documentation

CS-Script can be hosted by any CLR application. The easiest way to do this is to add it as a NuGet package.
CS-Script allows executing entire script files or C# code fragments. The very original implementation of hosted script execution was based on CodeDom API, which is available in all distributions of .NET and Mono. Thus it combines low dependency and ultimate portability.

Later CS-Script support alternative (compiler-as-service) compiling services has been added:
  • End of 2012 CS-Script v3.5: Mono Evaluator (Mono.CSharp.dll v.4.0.0.0)
  • End of 2015 CS-Script v3.10: Roslyn Compilers Beta release v1.2.0-beta-20151211-01

It is entirely up to developer to decide which compiling engine to use. The choice can be dictated by performance, deployment and maintainability considerations but not the convenience of the hosting API. This is because CS-Script encapsulates all three supported C# compilers into a single unified interface CSScript.Evaluator. Thus changing the compiling engine becomes a merely configuration exercise.

The evaluator allow executing either code fragments or entire class(es) definitions. Script can automatically access host types without any restrictions except types visibility (public vs. private). Scripted objects can be accessed dynamically (via 'dynamic') or statically via interface inheritance or duck-typing or via strongly typed delegates:

Accessing the script members dynamically:

dynamic script = CSScript.Evaluator
                         .LoadCode(@"using System;
                                     public class Script
                                     {
                                         public int Sum(int a, int b)
                                         {
                                             return a+b;
                                         }
                                     }");
         
int result = script.Sum(1, 2);

Loading strongly typed delegate:

var product = CSScript.Evaluator
                      .LoadDelegate<Func<int, int, int>>(
                                  @"int Product(int a, int b)
                                    {
                                        return a * b;
                                    }");
int result = product(3, 2);

Interface alignment (duck-typing). Note that class Script doesn't inherit from ICalc. Instead the script engine wraps the script object into dynamically generated proxy of ICals type:

public interface ICalc
{
    int Sum(int a, int b);
}
...
ICalc script = CSScript.Evaluator
                       .LoadCode<ICalc>(@"using System;
                                          public class Script
                                          {
                                              public int Sum(int a, int b)
                                              {
                                                  return a+b;
                                              }
                                          }");
      
int result = script.Sum(1, 2);

While Mono and Roslyn bring some benefits in many cases CodeDom driven execution remains the most practical solution. Particularly because it is the only solution that allows script debugging.
You can find all the details about the hosted script execution on this page: Hosted Script Execution.

Last edited Jan 15, 2016 at 12:08 AM by oleg_s, version 11