I'm developing a system which needs to support customization via a plugins module. I'm coding against interfaces so that plugin code only needs to implement these interfaces in order to be able to plug into the system.
// for illustration purposes; not actual code
public interface IPluggable
{
void Setup(PluginConfig c);
bool Process(IProcessable p);
}
I read from configuration which plugins need to be loaded, where the assembly name and fully-qualified type name are specified.
<plugin assembly="Foo.Bar.PluginAssembly" type="Foo.Bar.Plugins.AwesomePlugin" />
Where the type Foo.Bar.Plugins.AwesomePlugin
implements IPluggable
and is contained in the assembly Foo.Bar.PluginAssembly.dll
. With this information I proceed to create instances of the required plugins.
IPluggable plugin = (IPluggable)Activator.CreateInstance(assemblyName, typeName).Unwrap();
So my question is threefold:
- What would be a recommended pattern for a plugin system? Does the approach I'm taking make sense or are there any obvious flaws/caveats I'm missing?
- Is
Activator.CreateInstance()
a good choice for dynamically instantiating the plugin objects? - How can I be more specific about the assembly to load and its location? Say, if I want to load plugins only from assemblies located in a
.\plugins
subfolder.