#はじめに
RoslynでC#をスクリプトとして使えるようになってるんですね。
面白そうと思って試してみました。
しかし、スクリプトでLINQを使おうとすると実行時に例外を出されてしまうという問題にぶつかったので、それについて書いてみようと思います。
ところで、筆者は10年ぶりに趣味プログラミング再開したばかりの人で、C#も覚えたて、Qiitaも初投稿です。
なんか変なところがあったらそっと教えてください……
#usingできない?
次のような何の変哲もないスクリプトは実行できません。
using System.Linq;
//処理
こんなエラーが出ます。
”The type or namespace name 'Linq' does not exist in the namespace 'System' (are you missing an assembly reference?)”
どうしてスクリプトでSystem.Linqをusingしたときだけ怒られるのかわからず半日悩みました。(using Systemとかは普通に通る)
結論から言うと、"System.Core"をスクリプトでアセンブリ参照する必要があるようです。
#r "System.Core" //これを追加する
using System.Linq;
//処理
もしくは、スクリプトを呼び出す側でこう書きます。ScriptOptionsで指定してあげればスクリプトの側では#rもusingも書かなくていい。
var option = ScriptOptions.Default
.AddReferences("System.Core") //これが必要
.AddImports("System.Linq");
var code = File.ReadAllText(scriptpath);
var script = CSharpScript.Create(code, option);
この辺のオプション等の書き方も、Roslynのバージョンによって違いがあり、他のサイトで紹介されてる書き方ではダメだったりしました。
(インストールしているMicrosoft.CodeAnalysis.CSharp.Scriptingのバージョンは1.3.2)
以下のページにはそんな変更点も含めてまとめてありとても参考になりました。
http://wiki.clockahead.com/index.php?Coding%2F.NET%2FRoslyn%2FScripting#o8732c13
ともあれこれでスクリプトなのに簡潔に書けない悲しさが解決します。
#ついでに
呼び出し元で定義したクラスのインスタンスをスクリプト側に渡して操作できます。なんかすごい。
public class HogeClass
{
//何か
}
class Scripting
{
async Task RunScript()
{
var hoge = new HogeClass();
var option = ScriptOptions.Default
.AddImports("System");
var code = File.ReadAllText(scriptpath);
var script = CSharpScript.Create(code, option, typeof(HogeClass));
await Task.Run(() => { script.RunAsync(hoge); });
}
}