Well, reflection is *an* option, but interfaces are better;
Create a library which defines the functionality (methods, properties
etc) that your host provides. Reference this assembly from both your
host exe and your plugin dll. Now in the code where you make you host
available to the plugin, replace any class (code) references with the
interface (code) references - ideally making the plugin activation
code *also* work on interfaces.
e.g. (untested)
base assembly:
public interface IHost {
void DoSomethingHosty(int param1, string param2);
}
public interface IPlugin : IDisposable {
void Initialize(IHost host);
}
public abstract class PluginBase : IPlugin {
private readonly IHost _host;
public Host Host {get{return _host;}}
protected PluginBase() {}
protected virtual void Initialize(IHost host) {_host = host;}
public void Dispose() {Dispose(true);}
// and possibly a finalizer with Dispose(false), etc
protected virtual void Dispose(bool disposing) {}
}
plugin assembly:
public class MyPlugin : PluginBase {
void SomeRandomMethodOrEventHandler() {
Host.DoSomethingHosty(5,"abc");
}
void Initialize(IHost host) {
base.Initialize(host);
// other specific init steps
}
// override Dispose(bool) as necessary
// etc
}
host assembly:
public class MyHost : IHost, IDisposable {
public void DoSomethingHosty(int param1, string param2) {
MessageBox.Show(param1.ToString(), param2);
// whatever
}
void LoadPlugins() {
// TODO: load assembly and locate type
IPlugin plugin = (IPlugin) Activator.CreateInstance(pluginType);
plugin.Initialize(this);
myPluginCollection.Add(plugin);
}
public void Dispose() {Dispose(true);}
void Dispose(bool disposing) {
if(disposing) {
foreach(IPlugin plugin in myPluginCollection) {
try {plugin.Dispose();} catch {} // best endeavors
}
myPluginCollection.Clear();
}
}
}
***
As a random off-the-cuff third option; synamic assembly creation.
**way** OTT for this though ;-p