Deterministically order plugins, create cross-plugin call mechanism
Added a PluginManager.Call(function_name, ...) that allows plugins to
call functions by name. The plugin manager searches all plugins for
functions matching the name and signature of the arguments, then calls
each in turn. It in effect creates a simple message-passing system
where callers and callees are anonymous.
Added DeleteSession() to Session, and modified Vimish's command-line to
use the above Call system for non-internal functions.
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;
}
p.Init(wt);
Plugins[t.FullName] = p;
Console.WriteLine("Successfully loaded {0}", t.FullName);
+ PluginOrder.Add(t.FullName);
}
}
}
public void WebViewSetup(WebView view) {
- foreach (string key in Plugins.Keys) {
+ foreach (string key in PluginOrder) {
Plugins[key].InitWebView(view);
}
}
public void Deinit() {
- foreach (WebThingPlugin p in Plugins.Values) {
- p.Deinit(wt);
+ // 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;
+ }
}
}
Options[SessionName] = String.Join(" ", Uris.ToArray());
SaveConfig();
}
+
+ public void DeleteSession(string SessionName) {
+ Options.Remove(SessionName);
+ SaveConfig();
+ }
}
Options[args[1]] = args[2];
ApplyOptions();
break;
+ default:
+ bool found;
+ if (args.Length > 1) {
+ string[] callargs = new string[args.Length - 1];
+ Array.Copy(args, 1, callargs, 0, args.Length - 1);
+ found = wt.Plugins.Call(args[0], callargs);
+ if (!found)
+ Error("No function {0}({1}) found", args[0], String.Join(", ", callargs));
+ } else {
+ found = wt.Plugins.Call(args[0]);
+ if (!found)
+ Error("No function {0}() found", args[0]);
+ }
+ if (found)
+ Console.WriteLine("Plugin function {0} called successfully", args[0]);
+ break;
}
CommandlineHide();
}