C#でのスクリプトまたは実行時の動的実行

こんにちは、Habr!





C#が他の言語からのevalのようなものを持っていることを知っている人はほとんどいないと思います。Roslyn APIのおかげで、実行時にC#コードをコンパイルして実行できます。C#のREPL実装 での使用例を見ることができます





Pythonに触れたとき、最初にREPLのようなものに出会いました。 .NETの世界にもC#Interactive(CSI)と呼ばれる同様のものがあります。非常に便利なことですが、大きな欠点が1つあります。VisualStudioツールに含まれているため、VSをインストールしないと使用できません。また、VSを起動せずに実行するには、に登る必要があります。その深さ(または、コンソールC:\ Program Files(x86)\ Microsoft Visual Studio \ 2019 \ Community \ Common7 \ Tools \ VsDevCmd.batを介して実行)。これは、十分に便利なソリューションではない可能性があります。





dotnet-scriptcs-scriptMicrosoft.CodeAnalysis.CSharp.Scriptingを介して動作します)のようなプロジェクトもありますが、致命的な欠陥があります-それらは私が書いたものではありません。それで、あなた自身の不器用な自転車を書くというアイデアが生まれましたが、それ自身の機能(これも不器用に機能します)を備えています!。短い検索の後、私の目はこの奇跡に目を向けました:Microsoft.CodeAnalysis.CSharp.Scripting利点の1つは、便利なAPIであり、クラスや名前空間なしでコードを実行できることです。





まず、Microsoft.CodeAnalysis.CSharp.Scriptingパッケージをインストールし、使用する必要があります





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



CSharpScriptは、スクリプトの作成に役立つ静的クラスであり、次の3つのメソッドが含まれています。





  • 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/a7319e2bc8cac34c34527031e6​​204d383d29d4ab/src/Scripting





私の最初の記事がそれほど退屈に見えなかったことを願っています、そして私は何とかしてあなたを助けることができました。





良い一日を!








All Articles