A couple of months ago I implemented a simple control builder in a test application to generate dynamic controls using the System.Activator of the .NET Framerwork. The class added the created control to a ControlCollection (what a coincidence). It worked very well, but it suffered from two flaws- 1.) I had to maintain a disgusting switch statement for any type of control that I wanted to render, and 2.) I had to recompile when I needed additional control support.
In order to avoid the switch statement and the recompile, I needed to perform the same operations, but use a cached configuration file to provide the controls required for render instead of the switch statement. I managed to implement this using Reflection instead of using the System.Activator - naturally I ran into some problems that lead me to this solution.
In order to use the Activator's "CreateInstance" method you need to specify the object's Type (the easiest overloaded memeber IMO). I recently learned that the GetType( string typeName ) method of the System.Type namespace only works on initialized objects (would defeat the purpose of creating dynamic controls) and Types in the current working assembly (not sure if this is the right term). For instance, if you are in namespace MyProject.Web and have a type MyProject.Web.MyCustomPage the GetType( "MyProject.Web.MyCustomPage" ) will return a type object. However, if you need to perform GetType on MyOtherProject.WebControls.SomeCustomControl, you're out of luck because GetType only looks in the current assembly.
Okay, so how can I get the right assembly loaded so that the GetType looks in the correct assembly for the correct type name so that I can initialize my control? I started poking around the MSDN documentation looking into Reflection and I found out that the System.Reflection.Assembly object has the very same CreateInstance method for returning a type. Except that it requires an instance of the Assembly. Easy enough, right? Well, yes and no!
It's easy to create an Object in most OO languages, however, in order to create an instance of the assembly you need the fully qualified assembly name. So I built a quick console application that would write my assembly's fully qualified name (not the easiest, but it was quick and dirty) to a text file and I just copied that into the necessary constructor and voila. Assembly instance and now the ability to create an instance of any public, non-sealed member of that Assembly.
All that is left to do is build the config file for the dynamic controls and all will be right in the World. Stay tuned!