System.Reflection.Emit名前空間のTypeBuilderやMethodBuilderなどのクラスを使うと型情報やメソッドの実装を動的に生成し、実行することができます。 ただし、メソッドの実装にはILGeneratorクラスを使ってILコード(intermediate language, 中間言語コード)を記述する必要があるため、ILに関する知識が必要となります。
以下の例ではSystem.Reflection.Emit名前空間のクラスを使って以下のようなクラスを動的に生成し、作成したクラスのメソッドを呼び出しています。
System.Reflection.Emit名前空間のクラスを使って動的にクラスとメソッドを生成する
Imports System
Imports System.Reflection
Imports System.Reflection.Emit
Class Sample
Shared Sub Main()
' アセンブリ名"DynamicAssmembly"で動的にアセンブリを生成する
Dim assmName As New AssemblyName("DynamicAssmembly")
Dim assm As AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assmName, AssemblyBuilderAccess.Run)
' 作成したアセンブリ内にモジュール(VBのModuleではない)を宣言する
Dim mdl As ModuleBuilder = assm.DefineDynamicModule("DynamicModule")
' 作成したモジュール内にクラス(object型を基底クラスとした型)を宣言する
Dim typ As TypeBuilder = mdl.DefineType("HelloWorld", TypeAttributes.Public, GetType(Object))
' 作成したクラス内に戻り値がvoid(なし)、引数なしのパブリックメソッドを宣言する
Dim method As MethodBuilder = typ.DefineMethod("Print", MethodAttributes.Public, GetType(Void), Type.EmptyTypes)
' メソッドの実装となるILコードを生成する
Dim generator As ILGenerator = method.GetILGenerator()
generator.Emit(OpCodes.Ldstr, "Hello, world!")
generator.Emit(OpCodes.Call, GetType(Console).GetMethod("WriteLine", New Type() {GetType(String)}))
generator.Emit(OpCodes.Ret)
' 生成した型情報を使ってインスタンスを作成し、メソッドを呼び出す
Dim t As Type = typ.CreateType()
Dim inst As Object = Activator.CreateInstance(t)
t.InvokeMember("Print", BindingFlags.InvokeMethod, Nothing, inst, Nothing)
End Sub
End Class
実行結果
Hello, world!