C# - Dynamic Class Loading
April 5th, 2008 Michael ClarkeThe other day I wrote a small tutorial on getting dynamic class loading working for Java. In that post I mentioned that it could also be done in C# - but that it was more difficult, and from my personal experience, there is less information available about it - so here is how to do it!
First, as with the Java, we need to create our API. However, unlike the Java there is an additional requirement - a ‘module manager’ class needs to be within the API. As such you will need to create these two files…
using System; using System.Reflection;
namespace com.michaelclarkeblog.api {
public static class ModuleManager {
public static Module getInstance(String fileName) {
/* Load in the assembly. */
Assembly moduleAssembly = Assembly.LoadFile(fileName);
/* Get the types of classes that are in this assembly. */
Type[] types = moduleAssembly.GetTypes();
/* Loop through the types in the assembly until we find
* a class that implements a Module.
*/
foreach (Type type in types) {
if (type.GetInterface("Module") != null) {
/* Create a new instance of the 'Module'. */
return (Module)Activator.CreateInstance(type);
}
}
return null;
}
}
}
using System;
namespace com.michaelclarke.dynamic.api {
public interface Module {
String getText();
}
}
Once you’ve got the two files you can compile them into a library….
api $ mcs -t:library Module.cs ModuleManager.cs
api $ ls -a | grep .dll
Module.dll
api $
Now that we’ve made the API the next thing to write is the application that is going to use it for loading modules. This is a very simple application…
using System; using com.michaelclarkeblog.dynamic.api;
namespace com.michaelclarkeblog.dynamic.application {
public class Application {
public static void Main(String[] args) {
if (args.Length > 0 ) {
Module module = ModuleManager.getInstance(args[0]);
Console.WriteLine(module.getText());
} else {
Console.WriteLine("Usage: mono Application module_name");
}
}
}
}
Now we can compile our ‘Application’ against the API…
application $ mcs -reference:../api/Module.dll Application.cs application $ ls -la | grep exe -rwxr-xr-x 1 michaelfclarke michaelfclarke 3072 Apr 5 19:32 Application.exe application $
And now finally we can write a couple of modules!
using System;
using com.michaelclarkeblog.dynamic.api;
namespace com.michaelclarkeblog.dynamic.modules {
public class Mike : Module {
public String getText() {
return "Hello from Mike's Module!";
}
}
}
using System;
using com.michaelclarkeblog.dynamic.api;
namespace com.michaelclarkeblog.dynamic.modules {
public class Another : Module {
public String getText() {
return "Hello from Another Module!";
}
}
}
Compile the modules…
modules $ mcs -t:library -reference:../api/Module.dll Another.cs modules $ mcs -t:library -reference:../api/Module.dll Mike.cs modules $ ls -la | grep dll -rwxr-xr-x 1 michaelfclarke michaelfclarke 3072 Apr 5 19:36 Another.dll -rwxr-xr-x 1 michaelfclarke michaelfclarke 3072 Apr 5 19:36 Mike.dll modules $
There is just one last thing we need to do before we can run our application. We need to copy the Module.dll API from the api directory into the application directory…
modules $ cd ../application application $ cp ../api/Module.dll .
And now lets try running our dynamic application…
application $ mono Application.exe ../modules/Mike.dll Hello from Mike's Module! application $ mono Application.exe ../modules/Another.dll Hello from Another Module! application $ mono Application.exe Usage: mono Application module_name