Scripting di C # atau eksekusi dinamis saat runtime

Halo, Habr!





Saya pikir hanya sedikit orang yang tahu bahwa C # memiliki sesuatu seperti eval dari bahasa lain. Berkat Roslyn API, Anda dapat mengkompilasi dan mengeksekusi kode C # Anda saat runtime. Anda dapat melihat contoh penggunaan dalam implementasi REPL saya untuk C #.





Saya pertama kali bertemu hal seperti REPL ketika saya menyentuh python. Ada hal serupa di dunia .NET yang disebut C # Interactive (CSI). Hal yang cukup berguna, tetapi memiliki satu kelemahan besar - ini termasuk dalam alat Visual Studio, jadi tanpa menginstal VS, Anda tidak akan dapat menggunakannya, dan untuk menjalankannya tanpa memulai VS, Anda harus naik ke kedalamannya (atau lebih tepatnya, jalankan melalui konsol C: \ Program Files (x86) \ Microsoft Visual Studio \ 2019 \ Community \ Common7 \ Tools \ VsDevCmd.bat), yang mungkin bukan solusi yang cukup nyaman.





Ada juga proyek seperti dotnet-script dan cs-script (mereka bekerja melalui Microsoft.CodeAnalysis.CSharp.Scripting ), tetapi mereka memiliki kekurangan yang fatal - mereka tidak ditulis oleh saya. Jadi muncul ide untuk menulis sepeda kikuk Anda sendiri, tetapi dengan fitur-fiturnya sendiri (yang juga berfungsi dengan kikuk) !. Setelah pencarian singkat, mata saya tertuju pada keajaiban ini: Microsoft.CodeAnalysis.CSharp.Scripting . Salah satu keuntungannya adalah API yang nyaman, kemampuan untuk mengeksekusi kode tanpa kelas dan ruang nama.





Pertama, Anda perlu menginstal paket Microsoft.CodeAnalysis.CSharp.Scripting dan melakukan penggunaan





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



CSharpScript adalah kelas statis yang akan membantu kita membuat skrip, termasuk 3 metode:





  • 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





Saya harap artikel pertama saya tidak terlalu membosankan, dan saya bisa membantu Anda.





Semoga harimu menyenangkan!








All Articles