/PluginManager.cs
using System;
using System.Reflection;
using System.Collections.Generic;
using WebKit;

namespace bytex64.WebThing {
    public class PluginManager {
        public Dictionary<string,WebThingPlugin> Plugins;
        public List<string> PluginOrder;
        
        private WebThing wt;

        public PluginManager(WebThing wt) {
            Plugins = new Dictionary<string,WebThingPlugin>();
            PluginOrder = new List<string>();
            this.wt = wt;
        }

        public void Load() {
            foreach (string plugin in Config.Plugins) {
                LoadPlugin(plugin);
            }
        }

        public void LoadPlugin(string assemblyname) {
            Assembly a = FindAssembly(assemblyname);
            if (a == null) return;
            Type[] types = a.GetTypes();

            foreach (Type t in types) {
                if (t.IsSubclassOf(typeof(WebThingPlugin))) {
                    if (Plugins.ContainsKey(t.FullName))
                        continue;
                    WebThingPlugin p = (WebThingPlugin) a.CreateInstance(t.FullName, false, BindingFlags.ExactBinding, null, null, null, null);
                    p.Init(wt);
                    Plugins[t.FullName] = p;
                    Console.WriteLine("Successfully loaded {0}", t.FullName);
                    PluginOrder.Add(t.FullName);
                }
            }
        }

        private Assembly FindAssembly(string assemblyname) {
            foreach (string path in Config.PluginPath) {
                try {
                    return Assembly.LoadFile(path + "/" + assemblyname + ".dll");
                } catch {
                }
            }
            Console.WriteLine("Could not find {0}", assemblyname);
            return null;
        }

        public void WebViewSetup(WebView view) {
            foreach (string key in PluginOrder) {
                Plugins[key].InitWebView(view);
            }
        }

        public void Deinit() {
            // This reverses the plugin order on the assumption that it
            // will only be called once on program shutdown
            PluginOrder.Reverse();
            foreach (string key in PluginOrder) {
                Plugins[key].Deinit(wt);
            }
        }

        public bool Call(string funcname, params object[] args) {
            bool found = false;
            if (args.Length > 0) {
                foreach (string key in PluginOrder) {
                    WebThingPlugin plugin = Plugins[key];
                    Type ptype = plugin.GetType();

                    List<Type> types = new List<Type>();
                    foreach (object o in args)
                        types.Add(o.GetType());

                    MethodInfo method = ptype.GetMethod(funcname, types.ToArray());
                    if (method == null) continue;
                    method.Invoke(plugin, args);
                    found = true;
                }
            } else {
                foreach (string key in PluginOrder) {
                    WebThingPlugin plugin = Plugins[key];
                    Type ptype = plugin.GetType();

                    MethodInfo method = ptype.GetMethod(funcname, new Type[] {});
                    if (method == null) continue;
                    method.Invoke(plugin, null);
                    found = true;
                }
            }
            return found;
        }
    }
}