Reflection and Reflection.Emit in VB.NET: Part 1

In this article I will explain you about Reflection and Reflection.Emit in VB.NET.
  • 2822

The Reflection.Emit namespace classes can be used to emit Microsoft intermediate language (MSIL) code on the fly so that the generated code can be executed directly. Reflection is also used to obtain information about a class and its members. In other words, reflection is a technology that allows you to examine metadata that describes types and their members. You may have programmatically accessed Component Object Model type libraries before; reflection in .NET is very similar, but it is a lot more powerful and a lot easier to use. When you compile a source file with a .NET compiler, the compiler emits the MSIL of the statements within the source file, along with the metadata that describes the types defined within the file. It is this metadata that the reflection APIs in .NET enable you to examine. The MSIL and metadata are contained in assembly files (typically .dll and .exe files).

The reflection API in .NET uses the System.Reflection namespace. In this namespace are classes used to help you access structures inherent in a program such as classes, types, fields, structures, enumerators, members, and methods. For example, you use the Type class to identify the type of the class being reflected, and the FieldInfo class represents the fields of a structure or enumerator. The MemberInfo class represents the members of the reflected class, and you use the MethodInfo class to represent methods of the reflected class. The ParameterInfo class represents the parameters of a method in the reflected class.

You can create code at runtime with the System.Reflection.Emit namespace classes, but we must warn you that you must have some knowledge of the MSIL operation codes and the MSIL language to take advantage of the emitting commands. In fact, what you are actually emitting is the MSIL itself behind the scenes. You can use reflection to define an assembly in memory, create a class/module for that assembly, and then create other module members plus new types for that module. You can construct the assembly using emitting. Reflection.Emit is a powerful namespace in which we can dynamically emit transient and persisting assemblies at runtime. Reflection.Emit produces a low-level, language-neutral MSIL. Normally, we create an assembly by saving its source code to disk and then compiling that source code. Then we call the methods of classes that we need to use from that assembly, which was compiled on disk. But as you can imagine, this involves extra disk write and read effort! With reflection emit, we can omit this overhead and immediately emit the operation codes directly into memory. Reflection emitting is nothing but writing any assembly code directly within your code and then invoking the resulting code on the fly.
 

The ILGenerator.OpCodes class, which generates MSIL instructions, includes all the MSIL operation codes in its fields that you will need (operation codes are a portion of a set of operation descriptions that specifies the operation to be performed or the set of operations in a computer). MSIL is the typeless operation code of the base assembly language for the CLR or intermediate language. When you code any VB.NET code and compile it, it is transformed into MSIL first. Then when you invoke an assembly in MSIL, it is converted and executed in the corresponding machine language. The easiest way to learn MSIL is to disassemble simple codes that you have compiled. You can disassemble any compiled .NET code by using ILDasm.exe (the IL Disassembler), one of the .NET SDK utilities. After you have compiled the code in given below example and run it on the console, a new file is generated in your current folder called TestAsm.exe. This .exe file prints the message "Hello World" on the console.

Example of Creating an .exe File on the Fly (ReflectionEmit.vb)

    Imports System.Runtime
    Imports System.Reflection
    Imports System.Reflection.Emit
    Public Class class1
        Public Shared Sub Main()
            Dim ad As AppDomain = AppDomain.CurrentDomain
            Dim am As New AssemblyName()
            am.Name =
"TestAsm"
            Dim ab As AssemblyBuilder = ad.DefineDynamicAssembly(am, AssemblyBuilderAccess.Save)
            Dim mb As ModuleBuilder = ab.DefineDynamicModule("testmod", "TestAsm.exe")
            Dim tb As TypeBuilder = mb.DefineType("mytype", TypeAttributes.[Public])
            Dim metb As MethodBuilder = tb.DefineMethod("hi", MethodAttributes.[Public] Or MethodAttributes.[Static], Nothing, Nothing)
            ab.SetEntryPoint(metb)
            Dim il As ILGenerator = metb.GetILGenerator()
            il.EmitWriteLine(
"Hello World")
            il.Emit(
OpCodes.Ret)
            tb.CreateType()
            ab.Save(
"TestAsm.exe")
        End Sub
    End
Class

Try executing TestAsm.exe, and see whether it works as you expect. Indeed, we can accomplish anything by emitting operation codes that we can do with normal VB.NET code, since they both produce corresponding MSIL in the end.

Conclusion

Hope this article would have helped you in understanding the Reflection and Reflection.Emit in VB.NET. Some more discussion about Reflection and Reflection.Emit will on my next article.

Categories

More Articles

© 2020 DotNetHeaven. All rights reserved.