The limitations of Reflection.Emit

Question: Is Reflection.Emit a comprehensive API that lets you build any assembly you want?

Answer: No. There are some things that are valid IL, and yet can't be built with Reflection.Emit. Thanks to Eric Lippert for showing me the following example.

Why do we care about this? Partly it's just curiosity. Partly it's because we're porting the VB compiler from C++ into VB, and we wanted to know if we could use Reflection.Emit for the back-end (answer "no"). Partly because we're exploring the idea of a "REPL loop" and want to know how best to implement it (no solid answers yet).

Update: but as Rolf points out, the existing ResolveEventHandler in Reflection.Emit is inadequate. That's because it doesn't qualify the names. So if you were trying to emit this code, where everything is called "X", then the ResolveEventHandler wouldn't tell you which "X" it has in mind!

PublicClassX

Inherits N.X

PublicInterfaceX

EndInterface

EndClass

Namespace N

PublicClassX

ImplementsGlobal.X.X

EndClass

EndNamespace

Conclusion: if Reflection.Emit were to be used seriously, it'd have to be fixed first.

Well, it’s certainly not easy, but it can be done. The key is to subscribe to the AppDomain’s TypeResolve event, which will allow you to handle cyclical dependencies. However, you also need to treat the constructors explicitly to get a reference to Y’s constructor to call from X’s.

F# code follows (hopefully formatting won’t be mangled too badly). Ironically, I used F# because the REPL made rapidly iterating variations of the code quite easy.

Nice to see another VB compiler written in VB! And thanks for the badge!

Sidenote: there is a problem with with the TypeResolve event fix: you only get the name of the type, not the namespace. So by expanding the sample a little bit with types with the same name, but different namespace, you still have the same problem.

vbnc is now using SRE to create the assemblies (when I started writing vbnc there weren’t any alternatives), though I’m currently rewriting it to use another API (http://www.mono-project.com/Cecil).