Loading code-behind assemblies dynamically
I’m doing something similar to what Scott is doing, except I’m trying to either link or load the code-behind assemblies dynamically at run time.
I’m designing a plug-in framework for a project I’m working on. The idea is that other developers can reference our plug-in framework, implement our IPlugin interface, make a reference to their plugin in an XML config file, either for a specific page or for all pages in the application, and our plugin loader control will read the config file and instantiate the plugins specifed. Basically letting other developers add functionality to our application without their changes getting clobbered by our upgrades and new releases. Roy’s article is a great starting point, but it works best with detached assemblies. The code behind model in ASP.NET presents some interesting challenges. You can put the code behind assemblies in the /bin directory and have them automagically linked during the JIT compile, but as Scott points out in his post, that can clutter up the /bin directory a little. It also makes it a little difficult to version plugins. I want the developers to just plop the plugin in a /plugins directory and have it “just work”.
It’s pretty simple to load assemblies at runtime and create instances of the classes you want, once you grok the AppDomain and the Activator.CreateInstance method at least.
string baseDir = AppDomain.CurrentDomain.BaseDirectory;
ObjectHandle hndl = Activator.CreateInstanceFrom(baseDir + @"hellosTestAssembly.dll","TestAssembly.Class1");
IHello.IHello newObj = (IHello.IHello) hndl.Unwrap();
lblHello.Text = newObj.HelloWorld();
Scotts “probing” solution would work, but it requires the devs to modify the web.config, which could get clobbered. I’m starting to warm up to it a little more now that I’m thinking about it. At least until I solve the big problem, setting the probing property at runtime. I’m going to investigate the AppDomain.RelativeSearchPath property and the AppDomain.AppendPrivatePath method and see if I can set it at runtime, at least during application startup. I think if I were to do too much with them that I might impact the performance of the application. I’m also wondering if I’ll have to create a new AppDomain, like Roy did in his second article, and unwrap the proxies? I hope not, I’m pretty sure there’s a performance hit when you are crossing AppDomain boundries. The crux of this problem is that when you try to load a web control that uses the code behind model into your application you aren’t just loading one assembly dynamically, you are loading two and the second one isn’t created until runtime (essentially) and then not until the control is referenced. But the second one can’t be created until the first one is loaded and the appropriate code-behind class is instantiated. If I can load the code behind assemblies into the AppDomain during the application startup or link to them during the JIT compile, then loading the web controls is a snap.
If anyone has any suggestions or experience in these matters (e.g. “Scott you dummy you’re missing the obvious and making it more complicated than it needs to be!”) feel free to drop me a line, comment, or trackback to this post. I’ll be posting more on this later in the day/week as I learn more.
n.b. My first name is also Scott. The Scott I’m referring to in my “Scott you dummy…” line above is myself, not Scott H
-
http://www.computerzen.com Scott Hanselman
-
Derek Greer


