[C#][.NET][Roslyn] メタプログラミング入門 – Roslyn による Add メソッドの動的生成

Metasequoia

※ 「[C#][.NET] メタプログラミング入門 – 式木による Add メソッドの動的生成」の続き。

Roslyn によるメタプログラミング

前回は、式木を用いて Add メソッドを動的生成するプログラムを作成した。

今回は、Roslyn によるメソッドの動的生成だ。

Roslyn は、「Roslyn による Visual Studio のアドイン」で紹介したが、C# や Visual Basic のコンパイラーの内部の API 等を公開したものだ。

本稿執筆時点では CTP (Community Technology Preview) と呼ばれる評価版だが、これを用いて、C# のソースコードから、プログラムを生成することができる。

Roslyn のインストール

先ずは、Roslyn をインストールしよう。

Visual Studio の「ソリューション エクスプローラー」でプロジェクト名を右クリックし、「Nuget パッケージの管理…」を選ぶ。

Visual Studio の「Nuget パッケージの管理...」メニュー
Visual Studio の「Nuget パッケージの管理…」メニュー

「Nuget パッケージの管理」ダイアログボックスが開くので、右上の「オンラインの検索」エディット ボックスに「Roslyn」と入力し、検索する。

Visual Studio の「Nuget パッケージの管理」ダイアログボックス
Visual Studio の「Nuget パッケージの管理」ダイアログボックス

暫く待って表示されたリストの中から「Roslyn」を選び、「インストール」する。

動的に生成するメソッド

今回も次の Add メソッドを生成する。

// 普通の静的な Add メソッド
static int Add(int x, int y)
{
return x + y;
}

Roslyn を使うソースコードは次のようになる。

using Roslyn.Scripting.CSharp;
using System;
static class Program
{
// Roslyn による Add メソッドの生成
static Func<int, int, int> AddByRoslyn()
{
var engine  = new ScriptEngine(); // C# のスクリプトエンジン
var session = engine.CreateSession();
session.ImportNamespace("System"); // System 名前空間のインポート
return (Func<int, int, int>)session.Execute(code: "(Func<int, int, int>)((x, y) => x + y)");
}
static void Main()
{
var addByRoslyn    = AddByRoslyn();     // デリゲートを動的に生成
var answerByRoslyn = addByRoslyn(1, 2); // 生成したメソッドの呼び出し
Console.WriteLine("answerByRoslyn: {0}", answerByRoslyn);
}
}

C# のソースコードを直接扱えるので、Reflection.Emit を使った場合式木を使った場合
比較して、とても簡潔に書ける。

実行してみると、これも次のように正しく動作する。

answerByRoslyn: 3

まとめ

今回は、Roslyn を用いて、動的にメソッドを生成するプログラムを作成した。

これで三通りの方法を試したことになる。次回は、これらのパフォーマンスを比較してみよう。