Get Drunk on the Power of Reflection.Emit

Get Drunk on the Power of Reflection.Emit

# is a small language. It doesn’t support writing regular expressions, for example, or accessing a relational database, or even using simple data-structures like stacks, queues, and lists. Of course C# programmers use these things every day through class libraries that ship with .NET. The point is that text processing, data objects, and collections are platform features, not language features.

There’s nothing too surprising about using class libraries to supplement programming language facilities. What is surprising is that the .NET framework allows you to simulate the features of a dynamically typed language using C#.

This article will take you through the process of dynamically generating new types, methods, and even code at runtime with .NET. For a geek like me, this is an interesting exercise even if the code never makes it to production. But programmatically manipulating type information is more useful and more common than you might think. The .NET framework uses Reflection.Emit in diverse areas, from regular expressions to remoting. So who knows?maybe you’ll find a use for it too.

First Things First
Occasionally, C#’s static typing can seem excessively rigid. Let’s say I have two classes with identical interfaces:

[Serializable]public class Gun {   public virtual void Shoot()   {      MessageBox.Show("Bang!");   }}[Serializable]public class Camera {   public virtual void Shoot()   {      MessageBox.Show("Click!");   }}

Since the two types are so similar, it might be nice to treat them interchangeably?maybe iterate through a collection of guns and cameras, shooting each of them. But, you can’t because they don’t share a common base class or a common interface.

With access to the source code, adding an interface implementation is easy. But it turns out you can add an interface implementation dynamically as well using the Reflection.Emit namespace. The real advantage to this approach is that you only have to write the code once, and you can dynamically add an interface implementation to any class that exposes the necessary members.

Author’s Note: What’s with all the shooting?
I chose the names for these simple classes as a precautionary example. In general, .NET developers don’t attach semantics to a method signature outside the context of a type. So identical methods on unrelated types that don’t implement a common interface or share a common base class ? like Gun.Shoot() and Camera.Shoot()? may not offer similar functionality at all. The point is: be careful.

Conceptually, building types dynamically is exactly the same as writing code by hand. With the Reflection.Emit namespace, you can do anything at runtime that you can do at compile time?but often in a way that’s not so user friendly. Accordingly, my approach throughout this article will be to examine a static implementation first before showing you how to build the dynamic equivalent.

When building a standard, statically typed .NET application, the first thing you do is create a project. Similarly, before defining any dynamic classes, you need a place to put them. This part is pretty simple: Create a dynamic assembly, and then add a dynamic module. All of which should sound familiar because it’s exactly the same thing that your IDE does for you when you’re programming everyday. The only difference is that we’re doing this at runtime.

Here’s the code to dynamically build an assembly and a module:

AssemblyName an = new AssemblyName();an.Name = "ExtendedTypes";assemblyBuilder =      AppDomain.CurrentDomain.DefineDynamicAssembly      (an, AssemblyBuilderAccess.RunAndSave);      moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");    AppDomain.CurrentDomain.AssemblyResolve+=new ResolveEventHandler(OnAssemblyResolve);

Strategy #1: Subclassing On the Fly
Now it’s time to start dynamically implementing interfaces. But first, let’s review the plan. Both the Gun class and the Camera class need to implement a common interface called IShootable:

public interface IShootable{   void Shoot();}

If you were coding by hand, inheriting from a common interface would be very simple:

public class ShootableCamera: IShootable{}

You might have done something like the above when working with third-party components. The dynamic equivalent isn’t too much harder:

public Type Subclass  (ModuleBuilder builder,   Type target,   Type interfaceToImplement,   string newTypeName){   TypeAttributes attributes =      TypeAttributes.Public |     TypeAttributes.Serializable;   TypeBuilder tb =           moduleBuilder.DefineType("newTypeName ",    attributes, target);      tb.AddInterfaceImplementation(toImplement);   Type subClass = tb.CreateType();   return subClass;}
Figure 1. Your Gun Is Now IShootable: Now that you’ve dynamically added the interface, you can use the Gun class, wherever you’d use IShootable.

That code should look pretty straightforward. Here’s the English-language translation: “Define a new type (subclassing an existing type) and add an interface implementation.” The only non-intuitive line is the one containing the CreateType()?this is the method that “bakes in” any members, interfaces, etc, of the previous steps, and gets your new type ready for use.

That’s it. You’ve just build a subtype dynamically. Let’s give it a test run:

Type shootableGunType =   Subclass(     builder,       typeof(gun),     typeof(IShootable),      "ShootableGun");object shootableGun =   Activator.CreateInstance(       shootableGunType,       true);(shootableGun as IShootable).Shoot();

In the simplest case, all you have to do is create the subtype, create an instance of the subtype, and cast it to the appropriate interface (see Figure 1).

Mass Producing Your Dynamic Types
The next step is to figure out how to instantiate your dynamic type. The simplest method (shown above) is to use reflection, using Activator.CreateInstance(). But, there are a couple of problems with the reflection-based approach. First, there’s no obvious way to instantiate an object with a non-default set of parameters. Also, you might be wary of the poor performance that’s often associated with reflection (but more on that later).

An alternative to the reflection-based approach is to use the Prototype pattern. The idea here is to create new objects by copying a prototypical instance. The good news about using the prototype pattern is that it doesn’t require any reflection at all. Here’s the implementation:

class HydratingCopier{   readonly BinaryFormatter b       = new BinaryFormatter();    MemoryStream stream       = new MemoryStream();   public HydratingCopier       (object toSerialize)   {       factoryType=          toSerialize.GetType();       b.Serialize         (stream, toSerialize);   }   public object New()   {       stream.Position=0;       return b.Deserialize(stream);   }}

The advantage of this pattern is that you only have to use Activator.CreateInstance a single time?to create your initial prototype. After that, you can create new instances by “hydrating” a serialized copy?that is, populating the properties of the serialized copy with values.

The bad news is that this particular prototype implementation uses serialization. This puts a constraint on the target class: It must be serializable.

Strategy #2: Building Dynamic Adapters
If dynamically subclassing an object seems way too easy, you’ve got good instincts. It turns out that subclassing a type to add an interface has at least three limitations:

  • Methods of the base class must be explicitly marked as virtual.
  • The base class has to be a class, and not a struct.
  • The target class can’t be sealed.

So what’s the alternative to subclassing? One option is to dynamically build an object adapter that wraps the target class, and implements the specified interface. My approach here was inspired by a really cool CodeProject article by R?diger Klaehn called Autocaster.

Before you get into building more dynamic classes, take a look at the non-dynamic object adapter. The ShootableCameraAdapter wraps a Camera object to make it compatible with the IShootable interface:

public class ShootableCameraAdapter: IShootable{   private Camera wrappedCamera;   public ShootableCameraAdapter (Camera camera)   {      this.wrappedCamera = camera;   }   public void Shoot()   {      wrappedCamera.Shoot();   }}

Listing 1 looks convoluted, but it’s not doing any rocket science. Really, it’s just building a new type that implements the specified interface, and looping through the interface methods, adding a call to the wrapped object for each one. The only downside to this approach is that it doesn’t pass the substitution test. That is, you can’t substitute an instance of the wrapper type for an instance of the base type because they don’t participate in an inheritance relationship.

Thinking about Performance
I know what you’re thinking: Building types dynamically is interesting, but it must be an absolute pig, performance-wise. You’re right. Sort of. Reflection has a reputation for poor performance that’s well-deserved in certain areas. But remember that dynamically creating a new type is a one-time cost. Once the type is built, it’s compiled into an assembly just like any other type in .NET.

The process of copying prototype objects, however, incurs an ongoing performance penalty. Table1 shows the three different methods of instantiating dynamic types and, just for comparison, I also timed the creation of the baseclass using the new operator. Not surprisingly, using the new operator is the fastest. But instantiating dynamic types using reflection wasn’t too far behind. The prototype pattern ended up way behind the reflection-based approach, as deserialization proved to be the bottleneck.

Table 1. Hydration is the pig. When creating new instances of dynamic types, serialization ends up being the biggest performance penalty.

ApproachObjects created/second *
Hydration (Subclass)33,483
Hyrdration (Adapter)18,928
New Operator3,160,493

*My desktop has PentiumIV, and 1GB of RAM.

You should still consider these numbers with some perspective. In absolute terms, creating 18,000 objects per second isn’t too bad?even if it is two orders of magnitude slower than using the new operator. And there are ways to mitigate even these costs. Depending on the specifics of your application, you could build a factory class that copies prototypes on a low-priority worker thread, building up a cache of objects for when they’re needed.

Moderation in All Things
This is not idiomatic C#, not yet anyway. But the platform is still young, and the ability to dynamically create new types is one thing setting .NET apart from Java. After all, it took the C++ community years to discover the true power of templates. Maybe, over the next few years, we’ll all be taking advantage of the dynamic typing power of the .NET framework.


About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist