<= Home

Learning how to Emit

Posted about over 2 years ago

Just some advice if you ever want to create types on the fly during runtime.

 

I have been wanting to create my own proxy framework that supports aspect oriented programming for a while but was a little intimidated by the classes in System.Reflection.Emit. Actually though it’s not that hard though to get started I learned, by following these steps…

 

 

Example

So lets say you have an interface IHelloWorld you want to emit dynamically.

 

Public Interface IHelloWorld

    Function GetHelloWorld() As String

End Interface

 

Write a class similar to what you will want to emit.

 

Public Class MSILCodeExample

    Implements IHelloWorld

 

    Public Function GetHelloWorld() As String Implements IHelloWorld.GetHelloWorld

        Return "Hello"

    End Function

 

End Class

 

And then compile the code and look at the MSIL from ILDASM.

 

.method public newslot strict virtual final

        instance string  GetHelloWorld() cil managed

{

  .override CallDynamicClass.IHelloWorld::GetHelloWorld

  // Code size       11 (0xb)

  .maxstack  1

  .locals init ([0] string GetHelloWorld)

  IL_0000:  nop

  IL_0001:  ldstr      "Hello"

  IL_0006:  stloc.0

  IL_0007:  br.s       IL_0009

  IL_0009:  ldloc.0

  IL_000a:  ret

} // end of method MSILCodeExample::GetHelloWorld

 

To create this method during runtime your code would look similar to this:

 

    Private Sub CreateHelloWorldMethod(ByVal builder As TypeBuilder)

        Dim method As MethodBuilder = builder.DefineMethod("GetHelloWorld", MethodAttributes.Public, CallingConventions.Standard, GetType(String), New Type() {})

        Dim il As ILGenerator = method.GetILGenerator()

        Dim returnStatement As Label = il.DefineLabel()

 

        il.DeclareLocal(GetType(String))

 

        il.Emit(OpCodes.Nop)

        il.Emit(OpCodes.Ldarg, "Hello")

        il.Emit(OpCodes.Stloc_0)

        il.Emit(OpCodes.Br_S, returnStatement)

        il.MarkLabel(returnStatement)

        il.Emit(OpCodes.Ldloc_0)

        il.Emit(OpCodes.Ret)

    End Sub