Module system

MrLucky

Freshman
Joined
Mar 5, 2006
Messages
47
Ok, I want to try to create a module system.

I thought of a special folder with some DLL's as the modules. Each DLL must have a class and the class name must be the same as the filename. Each class has also 1 main function which I can call.

is it possible to create a reference or something for each DLL?
Is this a smart method, or is it better/easier to do it on an other way?

Thanks in advance :)
 
Ok, I've tried to create a module system, But I don't get it to work..

I have these 2 interfaces:
Both are saved in the same Assembly.

IHost.cs
C#:
using System;
using System.Collections.Generic;
using System.Text;

namespace IRCBot.Modules.Interfaces
{
	public interface IHost
	{
		void SendCommand(string command);
		void SendPM(string to, string message);
		void SendNotice(string to, string message);
		void MessageWindow(string message);
		void ErrorBox(string message);
		
		string CommandPrefix
		{
			get;
			set;
		}
		
		string Channel
		{
			get;
			set;
		}
		
		string Nick
		{
			get;
			set;
		}
		
		bool IsLoggedIn
		{
			get;
			set;
		}
		
		string ConnectionString
		{
			get;
			set;
		}
		
		System.Net.IRC IRC
		{
			get;
			set;
		}
	}	
}

IPlugin.cs
C#:
using System;
using System.Collections.Generic;
using System.Text;

namespace IRCBot.Modules.Interfaces
{
	public interface IPlugin
	{
		void Initialize(IHost Host);
		void CommandHandler(string command, string arguments);
		
		string Name
		{
			get;
		}
		
		string Description
		{
			get;
		}
		
		string Author
		{
			get;
		}
		
		string[] CommandsList
		{
			get;
		}
	}
}

Then my host application:

ModuleHost.cs
C#:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace IRCBot
{
	class ModuleHost : IRCBot.Modules.Interfaces.IHost
	{
		private System.Net.IRC irc_object;
		private string channel;
		private string nick;
		private string command_prefix;
		private string connection_string;
		private bool is_logged_in;
		
		public string CommandPrefix
		{
			get
			{
				return this.command_prefix;
			}
			set
			{
				this.command_prefix = value;
			}
		}
		
		public string Channel
		{
			get
			{
				return this.channel;
			}
			set
			{
				this.channel = value;
			}
		}
		
		public string Nick
		{
			get
			{
				return this.nick;
			}
			set
			{
				this.nick = value;
			}
		}
		
		public string ConnectionString
		{
			get
			{
				return this.connection_string;
			}
			set
			{
				this.connection_string = value;
			}
		}
		
		public bool IsLoggedIn
		{
			get
			{
				return is_logged_in;
			}
			set
			{
				is_logged_in = value;
			}
		}
		
		public System.Net.IRC IRC
		{
			get
			{
				return this.irc_object;
			}
			set
			{
				this.irc_object = value;
			}
		}
		
		public void SendCommand(string command)
		{
			this.IRC.SendCommand(command);
		}
		
		public void SendPM(string to, string message)
		{
			this.IRC.SendPM(to, message);
		}
		
		public void SendNotice(string to, string message)
		{
			this.IRC.SendNotice(to, message);
		}
		
		public void MessageWindow(string message)
		{
			MessageBox.Show(message);
		}
		
		public void ErrorBox(string message)
		{
			MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
		}
			
	}
}

ModuleHandler.cs
C#:
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Windows.Forms;

namespace IRCBot
{
	class ModuleHandler
	{
		public struct Module
		{
			public string Path;
			public string ClassName;
		}
		
		/// <summary>
		/// Searches for modules
		/// </summary>
		/// <param name="Path">Path to search</param>
		/// <param name="Interface">Interface name</param>
		/// <returns>array with all modules</returns>
		public static Module[] FindModules(string Path, string Interface)
		{
			ArrayList Modules = new ArrayList();
			string[] ModuleFiles;
			Assembly ModuleObject;
			
			ModuleFiles = Directory.GetFileSystemEntries(Path, "*.dll");
			for(int i = 0; i < ModuleFiles.Length; i++)
			{
				try
				{
					ModuleObject = Assembly.LoadFrom(ModuleFiles[i]);
					ExamineAssembly(ModuleObject, Interface, Modules);
				}
				catch
				{
					MessageBox.Show("Could not load plugin " + ModuleFiles[i]);
				}
			}
			
			Module[] Results = new Module[Modules.Count];
			
			if(Modules.Count != 0)
			{
				Modules.CopyTo(Results);
				return Results;
			}
			else
			{
				return null;
			}
		}
		
		/// <summary>
		/// Examines an assembly
		/// </summary>
		/// <param name="ModuleObject">Module Object</param>
		/// <param name="Interface">Interface name</param>
		/// <param name="Modules">Arraylist with all modules</param>
		public static void ExamineAssembly(Assembly ModuleObject, string Interface, ArrayList Modules)
		{
			Type oInterface;
			Module Module;
			
			foreach(Type ModuleType in ModuleObject.GetTypes())
			{
				if(ModuleType.IsPublic == true)
				{
					if((ModuleType.Attributes) != TypeAttributes.Abstract)
					{
						// Check if implement our interface
						oInterface = ModuleType.GetInterface(Interface, true);
						if(oInterface !=  null)
						{
							// It does =D
							Module = new Module();
							Module.Path = ModuleObject.Location;
							Module.ClassName = ModuleType.FullName;
							Modules.Add(Module);
						}
					}
				}
			}
		}
		
		/// <summary>
		/// starts a specific module
		/// </summary>
		/// <param name="Module">The module</param>
		/// <returns>an object with the class</returns>
		public static object StartModule(Module Module)
		{
			Assembly ModuleDLL;
			object oModule = null;
			
			try
			{
				ModuleDLL = Assembly.LoadFrom(Module.Path);
				oModule = ModuleDLL.CreateInstance(Module.ClassName);
			}
			catch(Exception ex)
			{
				MessageBox.Show("Could not starts module: " + ex.Message);
			}
			
			return oModule;
		}						
	}
}

And than, I'm using this piece of code in my Form1.cs file:

In Form_Load event:
C#:
			// Load Modules
			this.Modules = ModuleHandler.FindModules(System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "/modules", "IRCBot.Modules.Interfaces.IPlugin");
						
			this.Host = new ModuleHost();
			this.Host.CommandPrefix = this.CommandPrefix;

And this piece of code in a custom event: (Which triggers when a new command from the server is recieved)

C#:
				this.AddToLog("Setting host object..", "other");
				
				this.Host.IRC = irc;
				this.Host.Channel = channel;
				this.Host.Nick = nick;
				this.Host.ConnectionString = this.conn_string;
				this.Host.IsLoggedIn = this.IsLoggedIn(nick);

				this.AddToLog("Starting Modules.. - Number of modules: " + this.Modules.Length.ToString(), "other");
				IRCBot.Modules.Interfaces.IPlugin oModule;
				for(int i = 0; i < this.Modules.Length; i++)
				{
					this.AddToLog("Creating Object..", "other");
					oModule = (IRCBot.Modules.Interfaces.IPlugin) ModuleHandler.StartModule(this.Modules[i]);
					/*this.AddToLog("Initialize..", "other");
					oModule.Initialize(this.Host);*/
					
					this.AddToLog("Starting module: " + oModule.Name, "other");
					
					//oModule.CommandHandler(bot_command[0], arguments);
				}

A lot of code, I know :P

I build my Host application, no build errors.
The application also starts up with no errors.

But when I click my connect button, and my custom event triggers, I get the a problem.

When my app wants to create an instance of the plugin, it stops. My windows form is normal (can resize etc), but it does not handle any commands from the server anymore. It does nothing.. :S

What am I doing wrong?
 
Back
Top