Skip to content

Scripting API Samples

Tomáš Matoušek edited this page Jun 2, 2016 · 26 revisions

The scripting APIs enable .NET applications to instatiate a C# engine and execute code snippets against host-supplied objects. Below are examples of how to get started with the scripting APIs and some common samples. You can also view the Scripting API source code.

Supported Platforms

Scripting APIs require desktop .NET Framework 4.6+.

Scripting APIs can't be used within Universal Windows Applications and .NET Native since the application model doesn't support loading code generated at runtime.

Getting Started

Install the Scripting API NuGet Package:

Install-Package Microsoft.CodeAnalysis.CSharp.Scripting

Code Samples

Note: the samples require the following using:
using Microsoft.CodeAnalysis.CSharp.Scripting;

Scenarios


Evaluate a C# expression

object result = await CSharpScript.EvaluateAsync("1 + 2");

Evaluate a C# expression (strongly-typed)

int result = await CSharpScript.EvaluateAsync<int>("1 + 2");

Evaluate a C# expression with error handling

try
{
    Console.WriteLine(await CSharpScript.EvaluateAsync("2+2"));
}
catch (CompilationErrorException e)
{
    Console.WriteLine(string.Join(Environment.NewLine, e.Diagnostics));
}

Add references

var result = await CSharpScript.EvaluateAsync("System.Net.Dns.GetHostName()", 
     ScriptOptions.Default.WithReferences(typeof(System.Net.Dns).Assembly));

Add imports

var result = await CSharpScript.EvaluateAsync("Sqrt(2)", 
     ScriptOptions.Default.WithImports("System.Math"));

Parameterize a script

Note: there is a known bug here. A workaround would be to define Globals in a .dll and #r the .dll.

public class Globals
{
    public int X;
    public int Y;
}
var globals = new Globals { X = 1, Y = 2 };
Console.WriteLine(await CSharpScript.EvaluateAsync<int>("X+Y", globals: globals));

Create & build a C# script and execute it multiple times

var script = CSharpScript.Create<int>("X*Y", globalsType: typeof(Globals));
script.Compile();
for (int i = 0; i < 10; i++)
{
    Console.WriteLine(await script.RunAsync(new Globals { X = i, Y = i }));
}

Create a delegate to a script

The delegate doesn’t hold compilation resources (syntax trees, etc.) alive.

var script = CSharpScript.Create<int>("X*Y", globalsType: typeof(Globals));
ScriptRunner<int> runner = script.CreateDelegate();
for (int i = 0; i < 10; i++)
{
    await runner(new Globals { X = i, Y = i });
}

Run a C# snippet and inspect defined script variables

var state = await CSharpScript.RunAsync<int>("int answer = 42");
foreach (var variable in state.Variables)
     Console.WriteLine($"{variable.Name} = {variable.Value} of type {variable.Type}");

Chain code snippets to form a script

var script = CSharpScript.
    Create<int>("int x = 1;").
    ContinueWith("int y = 2;").
    ContinueWith("x + y");

Console.WriteLine((await script.RunAsync()).ReturnValue);

Continue script execution from a previous state

var state = await CSharpScript.RunAsync("int x = 1;");
state = await state.ContinueWithAsync("int y = 2;");
state = await state.ContinueWithAsync("x+y");
Console.WriteLine(state.ReturnValue);

Create and analyze a C# script

using Microsoft.CodeAnalysis;

var script = CSharpScript.Create<int>("3");
Compilation compilation = script.GetCompilation();
//do stuff

Compilation gives access to the full set of Roslyn APIs.

Customize assembly loading

using Microsoft.CodeAnalysis.Scripting.Hosting;

using (var loader = new InteractiveAssemblyLoader())
{
    var script = CSharpScript.Create<int>("1", assemblyLoader: loader);
    //do stuff 
}
Clone this wiki locally