メタプログラミング.NET
Windowsストアアプリの開発をしていたところ、Windows8.1環境が複数いることになり、ちょっと心が折れてしまいました。来月正式版がでるようなので、それを待って再開したいと思います。
それもあり、ASCIIから出たタイトルと同名の本に興味深い内容があったのでテストしてみました。
メタプログラムという、プログラムをプログラムする機能を使って、一つのコードから複数の.NET言語コードを生成してみました。
C++/CLI, C#, VB.NETの出力ができることを確認しましたが、それだけではつまらないと思い、VJ#とかやってみようと思いましたが、どうやら最近のVisualStdudioでは対応していないようです。F#も対応していないようです。
そして、本を読み進めていくとBooという言語があることを知りました。Mono(.NET互換環境)とかでよく使われているPythonに似た言語ということで、面白そうなのでこれを出力する方法調べてみました。
https://github.com/bamboo/boo にある、bin/Boo.Lang.CodeDom.dll をダウンロードして参照に追加します。
環境 : VisualStudio 2010 / Windows 7
using System; using System.IO; using System.Text; using System.CodeDom; using System.Diagnostics; using System.CodeDom.Compiler; class TestCodeDOM { static void Main() { CodeNamespace prgNamespace = BuildProgram(); var compilerOptions = new CodeGeneratorOptions() { IndentString = " ", BracingStyle = "C", BlankLinesBetweenMembers = false }; var codeText = new StringBuilder(); using (var codeWriter = new StringWriter(codeText)) { CodeDomProvider provider = new Boo.Lang.CodeDom.BooCodeProvider(); ICodeGenerator gen = provider.CreateGenerator(); CodeGeneratorOptions options = new CodeGeneratorOptions(); gen.GenerateCodeFromNamespace(prgNamespace, codeWriter, compilerOptions); } Console.WriteLine(codeText.ToString()); Console.ReadLine(); } static CodeNamespace BuildProgram() { var ns = new CodeNamespace("TestCode"); var systemImport = new CodeNamespaceImport("System"); ns.Imports.Add(systemImport); var programClass = new CodeTypeDeclaration("Program"); ns.Types.Add(programClass); var methodMain = new CodeMemberMethod { Attributes = MemberAttributes.Static, Name = "Main" }; methodMain.Statements.Add( new CodeMethodInvokeExpression( new CodeSnippetExpression("Console"), "WriteLine", new CodePrimitiveExpression("Hello world") ) ); programClass.Members.Add(methodMain); return ns; } }
これを実行すると以下のようなコードを出力します。
namespace TestCode
import Systemclass Program:
static def Main():
Console.WriteLine(“Hello world”)
言語プロバイダの部分を変更すると、VBやC#、C++も出力することができます。
CodeDomProvider provider = CodeDomProvider.CreateProvider("cpp");
.NETはいろんなことできるものですね。
ちょっと禁断の領域に足を踏み入れたかも・・