プログラミング C# - 翔ソフトウェア (Sho's)

C#/.NET/ソフトウェア開発など

メタプログラミング入門 - 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 を用いて、動的にメソッドを生成するプログラムを作成した。

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