Scripting en C # o ejecución dinámica en tiempo de ejecución

¡Hola, Habr!





Creo que pocas personas saben que C # tiene algo como eval de otros lenguajes. Gracias a la API de Roslyn, puede compilar y ejecutar su código C # en tiempo de ejecución. Puede ver un ejemplo de uso en mi implementación REPL para C #.





Conocí por primera vez algo como REPL cuando toqué Python. Hay algo similar en el mundo .NET llamado C # Interactive (CSI). Algo bastante útil, pero tiene un gran inconveniente: está incluido en las herramientas de Visual Studio, por lo que sin instalar VS, no podrá usarlo, y para ejecutarlo sin iniciar VS, debe ingresar sus profundidades (o más bien, ejecutar a través de la consola C: \ Archivos de programa (x86) \ Microsoft Visual Studio \ 2019 \ Community \ Common7 \ Tools \ VsDevCmd.bat), que puede no ser una solución lo suficientemente conveniente.





También hay proyectos como dotnet-script y cs-script (funcionan a través de Microsoft.CodeAnalysis.CSharp.Scripting ), pero tienen un defecto fatal: no fueron escritos por mí. Así que surgió la idea de escribir tu propia bici torpe, ¡pero con características propias (que además funcionan de forma torpe) !. Después de una breve búsqueda, mis ojos se posaron en este milagro: Microsoft.CodeAnalysis.CSharp.Scripting . Una de las ventajas es una API conveniente, la capacidad de ejecutar código sin clases ni espacios de nombres.





Primero, debe instalar el paquete Microsoft.CodeAnalysis.CSharp.Scripting y hacerlo usando





using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
      
      



CSharpScript es una clase estática que nos ayudará a crear un script, incluye 3 métodos:





  • Create - Script ,





  • RunAsync - , ScriptState





  • EvaluateAsync -





CSharpScript.Create , .





var script = CSharpScript.Create("System.Console.WriteLine(\"Hello from script\")");
script.Compile();
await script.RunAsync();
      
      



E Compile(), .





ScriptOptions, namespace- reference- ( , using static).





  var options = ScriptOptions.Default
            .AddImports("System", "System.IO", "System.Collections.Generic",
                "System.Console", "System.Diagnostics", "System.Dynamic",
                "System.Linq", "System.Text",
                "System.Threading.Tasks")
            .AddReferences("System", "System.Core", "Microsoft.CSharp");

 CSharpScript.Create("Console.WriteLine(\"Hello from script\")", options);
      
      



— ScriptOptions - namespace-. whitelist, , , .





CSharpScript.RunAsync ScriptState, ContinueWithAsync, , ScriptState. , Script. , ReturnValue.





ScriptState state = await CSharpScript.RunAsync("int x = 5;");
state = await state.ContinueWithAsync<int>("x + 1");
Console.WriteLine(state.ReturnValue); // 6
      
      



state , exception





foreach(var variable in state.Variables)
{
	Console.WriteLine($"{variable.Name} - {variable.Value}");
}
      
      



CSharpScript.Create ,





var script = CSharpScript.Create<Func<int,int>>("x => x+1");
Console.WriteLine(await script.CreateDelegate().Invoke(1)); // 2
      
      



, - , CSharpScript.EvaluateAsync ( , )





var deleg = await CSharpScript.EvaluateAsync<Func<int, int>>("x => x * 2");
Console.WriteLine(deleg(5)); // 10
      
      



- ( , , ).





CSharpScript globals globalsType (globalsType , globals), , ( CSharpScript.Create globalsType, script.RunAsync() globals).





var res = await CSharpScript.EvaluateAsync<int>("X+Y", globals: new GlobalValues());
Console.WriteLine(res); // 100

public class GlobalValues 
{
	public int X = 25;
	public int Y = 75;
}
      
      



:





, , . .





Microsoft.CodeAnalysis.CSharp.Scripting, , runtime C# . , , .net .





5 github, :





:





https://github.com/dotnet/roslyn/blob/main/docs/wiki/Scripting-API-Samples.md





https://github.com/dotnet/roslyn/tree/a7319e2bc8cac34c34527031e6204d383d29d4ab/src/Scripting





Espero que mi primer artículo no te haya parecido demasiado aburrido y pude ayudarte de alguna manera.





¡Que tenga un lindo día!








All Articles