ひまひまシリーズその 3。
今更ながら、System.CodeDom 名前空間の下のいくつかのクラスを使って
プログラムを組んでみました。
これ、慣れるまでには何回か組まないとコツがつかめないっぽい。
脳内でジェネレートされるプログラムを組み立てながらやったので(こんなお粗末なプログラムだが...)そのせいかも。
でも簡単な奴だったら Text ファイルなんかにテンプレート書いておいて
String.Format でやった方が楽かもしれない。
しかし、System.CodeDom.Compiler.CodeDomProvider に突っ込むオブジェクトの実態によって
C# やら VB やら複数種類のコード出力が可能なのは結構魅力的だと思いました。
ちょっと疑問な点が。
・コードに出力される Option Strict とかの設定はいったいどのオブジェクトがもっているの?
Microsoft.VisualBasic.VBCodeProvider が持っててよさそうな感じはするんだけどなぁ。
・Property の Set にパラメータが生成されない。CodeAssignStatement じゃだめなの?
CodeDomTest.vb
Public Class CodeDomTest
Public Sub Generate()
Dim compileUnit As System.CodeDom.CodeCompileUnit = _
New System.CodeDom.CodeCompileUnit()
' NameSpace
Dim nmspace As System.CodeDom.CodeNamespace = _
New System.CodeDom.CodeNamespace("CodeDomTry")
compileUnit.Namespaces.Add(nmspace)
' Imports
nmspace.Imports.Add( _
New System.CodeDom.CodeNamespaceImport("System"))
' Class
Dim cls As System.CodeDom.CodeTypeDeclaration = _
New System.CodeDom.CodeTypeDeclaration("CodeDomSample")
nmspace.Types.Add(cls)
cls.Comments.Add(New System.CodeDom.CodeCommentStatement("これはクラスヘッダのコメント"))
cls.IsClass = True
' Inherits
cls.BaseTypes.Add(GetType(Object))
' Implements(VB の場合最後に付ける)
cls.BaseTypes.Add(GetType(IDisposable))
' Constructor
Dim constructor As System.CodeDom.CodeConstructor = _
New System.CodeDom.CodeConstructor()
cls.Members.Add(constructor)
constructor.Attributes = CodeDom.MemberAttributes.Public
constructor.Comments.Add(New System.CodeDom.CodeCommentStatement("これはコンストラクタのコメント"))
' CodeConstructor の場合、自動で MyBase.New() が付加される。New という名前も勝手に付けてくれる
'constructor.Statements.Add( _
'New System.CodeDom.CodeMethodInvokeExpression( _
' New System.CodeDom.CodeBaseReferenceExpression(), "New", New System.CodeDom.CodeExpression() {}))
' Field
Dim field As System.CodeDom.CodeMemberField = _
New System.CodeDom.CodeMemberField(GetType(String), "m_propertyTest")
cls.Members.Add(field)
field.Comments.Add(New System.CodeDom.CodeCommentStatement("これはメンバ変数のコメント"))
' Property
Dim prop As System.CodeDom.CodeMemberProperty = _
New System.CodeDom.CodeMemberProperty()
cls.Members.Add(prop)
prop.Comments.Add(New System.CodeDom.CodeCommentStatement("これはプロパティのコメント"))
prop.Name = "PropertyTest"
prop.Type = New System.CodeDom.CodeTypeReference(GetType(String))
prop.Attributes = CodeDom.MemberAttributes.Public
Dim getter As System.CodeDom.CodeMethodReturnStatement = _
New System.CodeDom.CodeMethodReturnStatement()
getter.Expression = New System.CodeDom.CodeFieldReferenceExpression( _
New System.CodeDom.CodeThisReferenceExpression(), field.Name)
prop.GetStatements.Add(getter)
Dim setter As System.CodeDom.CodeAssignStatement = _
New System.CodeDom.CodeAssignStatement()
setter.Left = New System.CodeDom.CodeFieldReferenceExpression( _
New System.CodeDom.CodeThisReferenceExpression(), field.Name)
setter.Right = New System.CodeDom.CodePropertySetValueReferenceExpression()
prop.SetStatements.Add(setter)
' Method
Dim method As System.CodeDom.CodeMemberMethod = _
New System.CodeDom.CodeMemberMethod()
cls.Members.Add(method)
method.Comments.Add(New System.CodeDom.CodeCommentStatement("これはメソッドヘッダのコメント"))
method.Name = "TestMethod"
method.ReturnType = New System.CodeDom.CodeTypeReference(GetType(String))
method.Attributes = CodeDom.MemberAttributes.Public
Dim methodParameter As System.CodeDom.CodeParameterDeclarationExpression = _
New System.CodeDom.CodeParameterDeclarationExpression(GetType(Date), "value")
method.Parameters.Add(methodParameter)
Dim methodComment As System.CodeDom.CodeCommentStatement = _
New System.CodeDom.CodeCommentStatement("これはメソッド内のコメントです")
method.Statements.Add(methodComment)
Dim methodResultStatement As System.CodeDom.CodeMethodReturnStatement = _
New System.CodeDom.CodeMethodReturnStatement( _
New System.CodeDom.CodeMethodInvokeExpression( _
New System.CodeDom.CodeTypeReferenceExpression(methodParameter.Name), _
"ToString", New System.CodeDom.CodePrimitiveExpression("yyyy/MM/dd HH:mm:ss")))
method.Statements.Add(methodResultStatement)
' Implementation Method
Dim methodImple As System.CodeDom.CodeMemberMethod = _
New System.CodeDom.CodeMemberMethod()
cls.Members.Add(methodImple)
methodImple.Name = "Dispose"
methodImple.Attributes = CodeDom.MemberAttributes.Public
methodImple.ImplementationTypes.Add(GetType(IDisposable))
methodImple.Statements.Add(New System.CodeDom.CodeCommentStatement("TODO:実装してください"))
' Override Method
Dim methodoverride As System.CodeDom.CodeMemberMethod = _
New System.CodeDom.CodeMemberMethod()
cls.Members.Add(methodoverride)
methodoverride.Name = "ToString"
methodoverride.ReturnType = New System.CodeDom.CodeTypeReference(GetType(String))
methodoverride.Attributes = CodeDom.MemberAttributes.Public Or CodeDom.MemberAttributes.Override
methodoverride.Statements.Add(New System.CodeDom.CodeMethodReturnStatement( _
New System.CodeDom.CodeFieldReferenceExpression( _
New System.CodeDom.CodeThisReferenceExpression(), field.Name)))
' Generate
Dim provider As System.CodeDom.Compiler.CodeDomProvider = _
New Microsoft.VisualBasic.VBCodeProvider
'New Microsoft.CSharp.CSharpCodeProvider()
Dim generateOptions As System.CodeDom.Compiler.CodeGeneratorOptions = _
New System.CodeDom.Compiler.CodeGeneratorOptions()
generateOptions.BlankLinesBetweenMembers = True
generateOptions.IndentString = ControlChars.Tab
generateOptions.VerbatimOrder = True
provider.GenerateCodeFromCompileUnit(compileUnit, Console.Out, generateOptions)
End Sub
End Class
生成されたコード
'------------------------------------------------------------------------------
' <auto-generated>
' このコードはツールによって生成されました。
' ランタイム バージョン:2.0.50727.832
'
' このファイルへの変更は、以下の状況下で不正な動作の原因になったり、
' コードが再生成されるときに損失したりします。
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict Off
Option Explicit On
Imports System
Namespace CodeDomTry
'これはクラスヘッダのコメント
Public Class CodeDomSample
Inherits Object
Implements System.IDisposable
'これはコンストラクタのコメント
Public Sub New()
MyBase.New
End Sub
'これはメンバ変数のコメント
Private m_propertyTest As String
'これはプロパティのコメント
Public Overridable Property PropertyTest() As String
Get
Return Me.m_propertyTest
End Get
Set
Me.m_propertyTest = value
End Set
End Property
'これはメソッドヘッダのコメント
Public Overridable Function TestMethod(ByVal value As Date) As String
'これはメソッド内のコメントです
Return value.ToString("yyyy/MM/dd HH:mm:ss")
End Function
Public Overridable Sub Dispose() Implements System.IDisposable.Dispose
'TODO:実装してください
End Sub
Public Overrides Function ToString() As String
Return Me.m_propertyTest
End Function
End Class
End Namespace