I was working on a home project for creating a motion-detector that works using a webcam. Instead of using a baby-monitor I am planning to run this on an old computer. I'll point the web-cam to my daugthers' crib and the program would monitor both sound and her motions and ring an alarm in case she moves or makes any noise.

While working on this I wrote some code to support plugins to the application so that I can choose and use any motion-detection algorithm that I want. Some time back there was some questions on our internal DL about using late-binding to load and execute code. So I thought I'd blog about the code I used for the plugin loading and executing.

I used the following steps for this

  • List all dlls is a directory (plugins directory)
  • Load all assemblies from this dir
  • Iterate through all the types in the assembly and look if the type implements the plugin interface
  • Create an instance of the type that implement the interface and store it in a List

To do all of the above I wrote the following generic method that given any interface and a folder name can create a List of instances of all types that implement the plugin interface.

using System.Reflection;

using System.Collections.Generic;

public List<T> GetPlugins<T>(string folder)

{

string[] files = Directory.GetFiles(folder, "*.dll");

List<T> tList = new List<T>();

Debug.Assert(typeof(T).IsInterface);

 

foreach (string file in files)

{

try

{

Assembly assembly = Assembly.LoadFile(file);

foreach (Type type in assembly.GetTypes())

{

if (!type.IsClass || type.IsNotPublic) continue;

Type[] interfaces = type.GetInterfaces();

if (((IList)interfaces).Contains(typeof(T)))

{

object obj = Activator.CreateInstance(type);

T t = (T)obj;

tList.Add(t);

}

}

}

catch (Exception ex)

{

LogError(ex);

}

}

return tList;

}

With this method I can write code to show the list of plugins with their description in a menu or list control as follows

string exeName = Application.ExecutablePath;

string folder = Path.Combine(Path.GetDirectoryName(exeName), "Plugins");

List<IMotionDetector> list = GetPlugins<IMotionDetector>(folder);

 

m_listPlugin.Items.Clear(); // list box

foreach (IMotionDetector detector in list)

{

string name = detector.GetPluginName();

string desc = detector.GetPluginDescription();

string str = string.Format("{0}, {1}, {2}",

detector.GetType().FullName, name, desc);

m_listPlugin.Items.Add(str);

}

The interface I used is defined as

using System;

using System.Drawing;

namespace MotionDetector

{

// Event fired by the plugin on detecting motion

public delegate void MotionEvent(object sender, EventArgs args);

public interface IMotionDetector

{

// Plugin information - Since plugin det

string GetPluginName();

string GetPluginDescription();

 

void SetImage(Bitmap bitmap);

void Reset();

event MotionEvent Motion;

}

}

Since I used generics I marked the blog title with C#2.0.