はじめてのCodeDOM
Reflection.Emitに続いてCodeDOMを弄ってみました。C#、VB.NET両方のソースコードを吐き出すプログラムなんですが、苦労の割に報われない気が・・・(^^; これは手作業でやるものじゃないですね。
読みにくいですが、以下、ソースコードです。
using System; using System.IO; using System.CodeDom; using System.CodeDom.Compiler; using Microsoft.CSharp; using Microsoft.VisualBasic; class MyApp { [STAThread] static void Main(string args) { CodeCompileUnit unit = new CodeCompileUnit(); // 名前空間 CodeNamespace ns = new CodeNamespace("MyNamespace"); ns.Imports.Add(new CodeNamespaceImport("System")); // クラス CodeTypeDeclaration type = new CodeTypeDeclaration("MyApp"); // Fibメソッド CodeMemberMethod method = new CodeMemberMethod(); method.Name = "Fib"; method.Attributes = MemberAttributes.Static; method.ReturnType = new CodeTypeReference(typeof(void)); method.Parameters.Add( new CodeParameterDeclarationExpression(typeof(int), "num")); // 変数宣言 method.Statements.Add( new CodeVariableDeclarationStatement(typeof(int), "a")); method.Statements.Add( new CodeVariableDeclarationStatement(typeof(int), "b")); method.Statements.Add( new CodeVariableDeclarationStatement(typeof(int), "t")); method.Statements.Add( new CodeVariableDeclarationStatement(typeof(int), "i")); // 初期化 method.Statements.Add(new CodeAssignStatement( new CodeVariableReferenceExpression("a"), new CodePrimitiveExpression(0))); method.Statements.Add(new CodeAssignStatement( new CodeVariableReferenceExpression("b"), new CodePrimitiveExpression(1))); // ループ method.Statements.Add(new CodeIterationStatement( // 初期値 new CodeAssignStatement( new CodeVariableReferenceExpression("i"), new CodePrimitiveExpression(0)), // 継続条件 new CodeBinaryOperatorExpression( new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.LessThan, new CodeVariableReferenceExpression("num")), // 次へ new CodeAssignStatement( new CodeVariableReferenceExpression("i"), new CodeBinaryOperatorExpression( new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1))), // ループ内処理 new CodeStatement { new CodeExpressionStatement(new CodeMethodInvokeExpression( new CodeTypeReferenceExpression("Console"),"WriteLine", new CodeExpression { new CodeVariableReferenceExpression("b")})), new CodeAssignStatement( new CodeVariableReferenceExpression("t"), new CodeVariableReferenceExpression("a")), new CodeAssignStatement( new CodeVariableReferenceExpression("a"), new CodeVariableReferenceExpression("b")), new CodeAssignStatement( new CodeVariableReferenceExpression("b"), new CodeBinaryOperatorExpression( new CodeVariableReferenceExpression("b"), CodeBinaryOperatorType.Add, new CodeVariableReferenceExpression("t")))})); // Mainメソッド CodeMemberMethod main = new CodeMemberMethod(); main.Name = "Main"; main.ReturnType = new CodeTypeReference(typeof(void)); main.Attributes = MemberAttributes.Static; main.Comments.Add(new CodeCommentStatement("CodeDomサンプル")); main.Statements.Add(new CodeExpressionStatement( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(type.Name), method.Name, new CodeExpression {new CodePrimitiveExpression(20)}))); type.Members.Add(method); type.Members.Add(main); ns.Types.Add(type); unit.Namespaces.Add(ns); CodeGeneratorOptions opt = new CodeGeneratorOptions(); opt.ElseOnClosing = true; opt.BlankLinesBetweenMembers = true; // C#ソースファイル生成 using (StreamWriter sw = new StreamWriter("fib.cs")) { new CSharpCodeProvider().CreateGenerator() .GenerateCodeFromCompileUnit(unit, sw, opt); } // VB.NETソースファイル生成 using (StreamWriter sw = new StreamWriter("fib.vb")) { new VBCodeProvider().CreateGenerator() .GenerateCodeFromCompileUnit(unit, sw, opt); } } }
生成されたC#ソースファイル(fib.cs)
namespace MyNamespace { using System; public class MyApp { static void Fib(int num) { int a; int b; int t; int i; a = 0; b = 1; for (i = 0; (i < num); i = (i + 1)) { Console.WriteLine(b); t = a; a = b; b = (b + t); } } // CodeDomサンプル static void Main() { MyApp.Fib(20); } } }
Option Strict Off Option Explicit On Imports System Namespace MyNamespace Public Class MyApp Shared Sub Fib(ByVal num As Integer) Dim a As Integer Dim b As Integer Dim t As Integer Dim i As Integer a = 0 b = 1 i = 0 Do While (i < num) Console.WriteLine(b) t = a a = b b = (b + t) i = (i + 1) Loop End Sub 'CodeDomサンプル Shared Sub Main() MyApp.Fib(20) End Sub End Class End Namespace