Skip to Content
Course content

141: Practice Exercise: Building a Simple Plugin Loader with Reflection

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Think of a plugin system like a universal power socket in your wall. The socket doesn't know if you're going to plug in a lamp, a vacuum cleaner, or a toaster. It doesn't care about the internal circuitry of the appliance; it only cares that the plug fits the holes and operates at the right voltage. As long as the appliance follows that "contract," the house provides the power, and the appliance does its job.

In C#, Reflection is how we build that socket. We define an interface (the socket shape), and then we use Reflection to look at a compiled DLL file (the appliance), check if it has a class that fits that interface, and if it does, we "plug it in" and run it—all without the main program ever having a hard-coded reference to that plugin project.

The Contract: Defining the Interface

Before we can load anything dynamically, we need a shared language. I usually put this in a separate, tiny class library project that both the main app and the plugins reference. If the main app doesn't know what the interface is, it can't cast the reflected type to anything useful.

public interface IPlugin
{
    string Name { get; }
    void Execute();
}

This is our "socket." Any class that implements IPlugin is now compatible with our loader.

The Magic Trick: Scanning the DLL

Here is where the actual Reflection happens. We aren't using new PluginClass() because we don't know the name of PluginClass at compile time. Instead, we load the assembly from a file path and sift through its types.

using System.Reflection;

// Load the assembly from the disk
Assembly pluginAssembly = Assembly.LoadFrom("MyCoolPlugin.dll");

// Find all types that implement IPlugin and aren't abstract
var pluginTypes = pluginAssembly.GetTypes()
    .Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);

foreach (var type in pluginTypes)
{
    // Create an instance of the type
    IPlugin plugin = (IPlugin)Activator.CreateInstance(type);
    Console.WriteLine($"Loaded: {plugin.Name}");
    plugin.Execute();
}

I'll let you in on a secret: Activator.CreateInstance is the heavy lifter here. It looks at the type we found via Reflection and tells the CLR, "I don't know exactly what this is, but I know it has a constructor. Go ahead and make one."

Tying it Together in the Main Loop

In a real-world scenario, you wouldn't just load one hard-coded DLL. You'd probably point your app at a /plugins folder and loop through every .dll file found there. This allows you to add new functionality to your software just by dropping a file into a folder—no recompiling the main executable required.

One thing to keep in mind: Reflection is slower than direct calls. If you're calling a plugin method ten thousand times a second in a tight loop, you'll feel the performance hit. But for loading a module at startup? It's a negligible cost for a massive gain in flexibility.




📋 Practical Task

Build a Dynamic Text-Processing Pipeline

Your goal is to create a system where the main application can load various "Text Processors" from external DLLs to transform a string of text.

Requirements:

  • Create an interface called ITextProcessor with a method string Process(string input).
  • Create a separate Class Library project that implements ITextProcessor. Create at least two classes in this library: one that converts text to UPPERCASE and one that reverses the string.
  • In your main Console Application, implement a loader that:
    1. Scans a specific folder for .dll files.
    2. Uses Reflection to find all classes implementing ITextProcessor.
    3. Instantiates them and passes a sample string (e.g., "Hello Reflection!") through each processor, printing the result of each to the console.

Pro Tip: Make sure your plugin DLL is actually copied to the output folder of your main application, or provide the absolute path to the DLL in your Assembly.LoadFrom call, otherwise you'll run into FileNotFoundException.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.