Script en C # ou exécution dynamique à l'exécution

Bonjour, Habr!





Je pense que peu de gens savent que C # a quelque chose comme eval d'autres langages. Grâce à l'API Roslyn, vous pouvez compiler et exécuter votre code C # au moment de l'exécution. Vous pouvez voir un exemple d'utilisation dans mon implémentation REPL pour C #.





J'ai rencontré pour la première fois une chose telle que REPL lorsque j'ai touché python. Il existe une chose similaire dans le monde .NET appelée C # Interactive (CSI). C'est assez pratique, mais il a un gros inconvénient - il est inclus dans les outils Visual Studio, donc sans installer VS, vous ne pourrez pas l'utiliser, et pour l'exécuter sans démarrer VS, vous devez monter dans ses profondeurs (ou plutôt via la console C: \ Program Files (x86) \ Microsoft Visual Studio \ 2019 \ Community \ Common7 \ Tools \ VsDevCmd.bat), ce qui n'est peut-être pas une solution assez pratique.





Il existe également des projets comme dotnet-script et cs-script (ils fonctionnent via Microsoft.CodeAnalysis.CSharp.Scripting ), mais ils ont un défaut fatal - ils n'ont pas été écrits par moi. Alors l'idée est venue d'écrire votre propre vélo maladroit, mais avec ses propres caractéristiques (qui fonctionnent aussi maladroitement)!. Après une brève recherche, mes yeux sont tombés sur ce miracle: Microsoft.CodeAnalysis.CSharp.Scripting . L'un des avantages est une API pratique, la possibilité d'exécuter du code sans classes ni espaces de noms.





Tout d'abord, vous devez installer le package Microsoft.CodeAnalysis.CSharp.Scripting et utiliser





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



CSharpScript est une classe statique qui nous aidera à créer un script, comprend 3 méthodes:





  • 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





J'espère que mon premier article n'a pas semblé trop ennuyeux, et j'ai pu vous aider d'une manière ou d'une autre.





Bonne journée!








All Articles