Browse DevX
Sign up for e-mail newsletters from DevX


Reflection Part II: Emit : Page 4

In our previous article, Reflection Part 1: Discovery and Execution , we introduced the System.Reflection namespace and its classes which allow developers to view assembly metadata, query for and discover types, and invoke code—all at run-time. In this article we will examine reflection emit—the ability to dynamically generate code at runtime.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Coupling Emit and Dynamic Invocation
Now that you know how to emit a dynamic assembly using the Reflection classes, let's integrate the concept of dynamic invocation (covered in Part 1 of this article).

One example of when to use Reflection and Reflection.Emit is with code or script evaluation at run-time. It would be possible, for instance, to display a Windows form with a text box, ask the user to type in a formula, and then evaluate that formula at run-time through compiled code.

Another time to use Reflection.Emit classes is to optimize performance. Code solutions, by design, tend to be generalized solutions to a problem. This is often a good thing from a design perspective because it makes your systems flexible. For instance, if you want to compute the sum of numbers and you don't necessarily know at design time how many values you need to sum, then you may need to call a loop. If you rewrite the ReturnSum function to accept an array of integers, you could loop through the members of that array, add each to a counter value, and then return the sum of all of the values. This is a nice generic solution since it doesn't care about the total number of values contained in the array.

Public Function ReturnSum(ByVal values() _ As Integer) As Int32 Dim i As Int32 Dim retValue As Int32 For i = 0 To values.GetUpperBound(0) - 1 retValue = retValue + values(i) Next Return retValue End Function

On the other hand, if you hard-code the array limit you can return the sum in a more optimized fashion by writing one long math operation statement. For a few values or even hundreds of values the difference would be negligible. But, if you're dealing with thousands or millions of values, the hard-coded method will be much, much faster. In fact, you can make this solution even faster by pulling out the array values and summing them with straight number addition while at the same time eliminating any 'zero' values that won't affect the result anyway:

Public Function ReturnSum() As Int32 Return 9 + 32 + 8 + 1 + 2 + 2 + 90 '... End Function

The problem here, of course, is that you've written code that is not general and is not flexible.

So how do you get the best of both worlds? Answer: Reflection.Emit.

By combining Reflection.Emit functionality (such as taking in an array ceiling and array values, and then compiling the code), and Reflection functionality (such as locating, loading, and running the assembly that was emitted), you can craft some pretty ingenious performance solutions while avoiding brittle code. In this simple case you could write a loop that generates the MSIL op codes you need.

Consider the following console application that consumes an array and creates a new assembly, module, class, and ReturnSum method that directly sums the array values without resorting to a loop. The code in Listing 1 showcases many of the same concepts you've already seen in terms of using the emit "builder" objects. Please note some new code that is introduced with the application: Activator.CreateInstance is used to create an instance of the newly created object type, and the InvokeMember method is used to call the ReturnSum method on the type.

Reflection and Reflection.Emit namespaces allow programmers to dynamically generate and execute managed code at run-time. They provide a highly specialized set of classes for dealing with a uniquely specialized set of business problems.

You can download the code for this article at www.brilliantstorm.com/resources.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date