Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jrgcubano/a643c05629a10e587dd5ff58e6d0b504 to your computer and use it in GitHub Desktop.
Save jrgcubano/a643c05629a10e587dd5ff58e6d0b504 to your computer and use it in GitHub Desktop.
Roslyn C# Scripting with Cache
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Scripting;
using Microsoft.CodeAnalysis.Scripting.CSharp;
namespace RoslynScriptingTest
{
/// <summary>
/// Pure sample code. No exception handling. (Syntax errors in scripts throw exceptions at RunAsync())
/// </summary>
public static class ScriptEngine
{
public static readonly Dictionary<string,Script> Scripts = new Dictionary<string, Script>();
private static IEnumerable<Assembly> _references;
/// <summary>
/// Executes and caches a script. Returns true if executed cached script.
/// </summary>
/// <param name="code">C# code to execute</param>
/// <returns>false if it had to be compiled. true if it had a cached version</returns>
public static async Task<bool> ExecuteAsync(string code)
{
if (Scripts.ContainsKey(code))
{
await Scripts[code].RunAsync();
return true;
}
var script = CSharpScript.Create(code, GetScriptOptions());
await script.RunAsync();
Scripts.Add(code, script);
return false;
}
/// <summary>
/// Forces building/compilation of the code you pass it. Caches the script for faster execution.
/// </summary>
/// <param name="code">C# code to compile and cache</param>
public static void PreCompile(string code)
{
var script = CSharpScript.Create(code, GetScriptOptions());
script.Build();
Scripts.Add(code, script);
}
/// <summary>
/// Extendable function to setup script options. Currently adding all referenced assemblies to the script engine.
/// </summary>
/// <returns>ScriptOptions with all currently loaded assemblies</returns>
private static ScriptOptions GetScriptOptions()
{
if(_references == null)
_references = AppDomain.CurrentDomain.GetAssemblies().Where(assembly=> assembly.Location != string.Empty);
return ScriptOptions.Default.WithReferences(_references);
}
}
public static class Program
{
private static void Main()
{
Task.Run(async () =>
{
Console.WriteLine("Test #1 - Executing same code twice. Should return: false, true");
Console.WriteLine("Cached: " + await ScriptEngine.ExecuteAsync(@"using System; Console.WriteLine(""Hello World"");"));
Console.WriteLine("Cached: " + await ScriptEngine.ExecuteAsync(@"using System; Console.WriteLine(""Hello World"");"));
Thread.Sleep(3000);
Console.WriteLine("Test #2 - Precompiling same code and executing twice. Should return: true, true");
ScriptEngine.Scripts.Clear();
ScriptEngine.PreCompile(@"using System; Console.WriteLine(""Hello World"");");
Console.WriteLine("Cached: " + await ScriptEngine.ExecuteAsync(@"using System; Console.WriteLine(""Hello World"");"));
Console.WriteLine("Cached: " + await ScriptEngine.ExecuteAsync(@"using System; Console.WriteLine(""Hello World"");"));
});
while (true)
{
Console.ReadLine();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment