• Welcome to Valhalla Legends Archive.
 

[C#] Plugin System Design

Started by Smarter, November 29, 2007, 06:02 AM

Previous topic - Next topic

Smarter

I'm currently attempting to design an efficent plugin system for my CompleteCore project, but I have yet to venture into such a task, so i'm a bit confused as to how to go about it. My current idea is to execute plugins is something along the lines of:


        /// <summary>
        /// Load's the specified plugin.
        /// </summary>
        /// <param name="pluginName">Plugin Name</param>
        public void loadPlugin(Plugin pluginName)
        {
            if (pluginList.Contains(pluginName))
            {
                pluginName = new Plugin.Plugin();
            }
            else
            {
                //Fail;
            }
        }

        /// <summary>
        /// Returns list of found plugins.
        /// </summary>
        public List<string> pluginList
        {
            get
            {
                List<string> Plugins = new List<string>();
                foreach (string s in Directory.GetFiles(Application.StartupPath + "\\Plugins"))
                {
                    Plugins.Add(s);
                }
                return Plugins.ToArray();
            }
        }


I have created a basic template for plugins in a namespace that will be compiled with the core, so I can have a basis on which to call default functions:


namespace CompleteCore.Plugin
{
    public class Plugin
    {
        public Plugin()
        {
            //Plugin Initializer; } }
        }
    }

    public class PluginInfo
    {
        public string Author { get {  "Smarter"; } }
        public string Version { get {  "0.0.1.0"; } }
        public string Website { get {  "http://www.Example.com"; } }
        public string Info { get {  "Some other information."; } }
    }
}


I'm not sure if this will even work, lol, it's just brainstorming any help would be appreciated.
Since '99

BrutalNet.Net

Banana fanna fo fanna

pluginName should be a string, not a Plugin.

I'm not sure how the .NET API does reflection and dynamic class loading, but google for it (Myndfyre should know how). When I designed PhatBot's plugin API, I essentially made each plugin expose the GreetBot callbacks. Now with binary bots, this would need to be tweaked a bit, but should give you a good idea of what to provide. When instantiating each plugin, I passed a "bot" object which contained a hashtable of different subsystems. For example, one plugin could add a subsystem to the object which another plugin could take advantage of (perhaps a user access database). Therefore, the bot "kernel" was tiny. It could parse and dispatch events, and added a basic subsystem that sent a line of text to battle.net, and that was it. On top of that framework I built the GUI, the scripting interface, user DB, etc.

I'd suggest hiding the plugin-ness of your application as much as possible; users often don't care about it, and invisible technology is the sign of good technology.

Smarter

I had it that way at first, then realized I couldn't initialize it (unless you know of another way?), and I had plans to have the plugin pass an instance of the CompleteCore to it, but I don't think I should play with the plugin system yet until I have all my call backs in place, but i'm still not sure as to how to properly design it, I guess I'll just wait on MyndFyre to poke his head around and bounce ideas off him ;). Thanks.
Since '99

BrutalNet.Net

Banana fanna fo fanna

rough idea in pseudo java:


interface Plugin {
    // initialize plugin instance and install any subsystems into the subsystems map
    public static Plugin getInstance(Map subsystems);
    public void onJoin(String username, String product);
    public void onLeave(String username);
    // ...
    // use subsystems map to communicate to bnet. define a standard list of subsystems
    // use subsystems to also handle stuff like configuration.
    // honestly, if this were python, subsystems would be an Adaptable object, but nevermind
}

Hell-Lord

Quote from: Banana fanna fo fanna on November 29, 2007, 03:20 PMI'd suggest hiding the plugin-ness of your application as much as possible; users often don't care about it, and invisible technology is the sign of good technology.

I personally don't like the idea of hiding it, but if you have to you could store the location of the path in a registry key. So basically the plugin has the path stored in it and you read it.

Smarter

Hmm, i've cleared up my thoughts a bit, I think the best way of going about it, would have the core have global call backs (obviously), that the plugin would be able to act upon, and define functions each callback would call, but how I would load a plugin into the core itself, and initialize it, is where i'm confused.
Since '99

BrutalNet.Net

Hell-Lord

You just need to load it into memory using Assembly.Load the plugin itself will handle or its own stuff in OnLoad() for example.