Thursday, September 27, 2012

Bye Bye ConstructorBuilder

System.Reflection.Emit is a great .NET feature, especially if you consider that it shipped as part of .NET 1.0, but the design of System.Reflection.Emit leaves something to be desired.

One of the crazy features is ConstructorBuilder. On the System.Reflection side, ConstructorInfo isn't all that helpful, but it is not as actively harmful as ConstructorBuilder. The reason for this is that ConstructorInfo and MethodInfo both extend MethodBase, so most common APIs are available through MethodBase.

ConstructorBuilder and MethodBuilder share no common Builder base class (because they extend ConstructorInfo and MethodInfo), this causes a lot of code duplication and type testing/downcasting.

A long time ago I found out that you can mostly avoid ConstructorBuilder, since it is possible to use TypeBuilder.DefineMethod() to define constructors. Recently I finally got around to taking advantage of this and completely removing ConstructorBuiler from the IKVM.NET runtime and compiler.

The thing that pushed me over the edge was this experiment. In .NET 2.0 there is no ConstructorBuilder equivalent to MethodBuilder.CreateMethodBody(). So if I'm ever going to experiment with method level JIT it is nice to be able to use this more efficient method of installing the stub.

There is one problem with using MethodBuilder for constructors. If you define a custom attribute and want to apply that custom attribute while it is still unbaked, you need a ConstructorBuilder for the custom attribute constructor, because CustomAttributeBuilder requires it. Luckily, in dynamic mode IKVM doesn't need to do this and in static mode I use IKVM.Reflection so I added MethodInfo.__AsConstructorInfo() to wrap the MethodInfo in a ConstructorInfo.

I considered adding MethodInfo support to CustomAttributeBuilder, but that turned out to be much more complicated, so I went with the easy approach of reusing the existing wrapping strategy.

The result of this refactoring is the removal of a bunch of duplicate code and a lot of downcasting. It also saves a small bit of memory, because the ConstructorBuilder wrappers are not needed anymore.

9/27/2012 2:29:05 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]