16. juni 2003 - 15:04Der er
11 kommentarer og 1 løsning
Program der loader egne plugins
Jeg sidder og arbejder med et system der skal kunne loade egne plugins, jeg er kommet så langt at jeg kan lave nogle simple plugins som bliver loadet i mit system. Jeg vil gerne lave noget mere advanceret som fx. at have min assembly til at indeholde nogle user controls, eller nogle nye knapper der så tilføjes til den eksisterende grænseflade. Eksempelvil loader man et plugin der hedder "Regnemaskine" skal der komme et nyt menupunkt der hedder "Regnemaskine" eller en eksisterende menu udbygges. Hvordan kringler man lige den???
Du skal lave et interface. Dette interface beskriver hvad din menupunkts klasse SKAL indeholde. Idet du vil lave et nyt menupunkt(en ny klasse), saa skal denne klasse implementere dette interface. Et eksempel kunne vaere:
public interface ITest { public System.Windows.Forms.MenuItem GetMenuItem(); }
Dette skal laegges i en assembly for sig selv.
Saa opretter du din plugin i en ny assembly(hvor du adder reference til ITest assemblyen):
public class TestPlugin : ITest { private System.Windows.Forms.MenuItem _menuItem; public TestPlugin() { _menuItem = new System.Windows.Forms.MenuItem(bla bla bla); _menuItem.Click += new Handler... }
public System.Windows.Forms.MenuItem GetMenuItem() // this one REQUIRED by ITest { return _menuItem;; }
public void OnClickMenuItem(bla bla) { //run code } }
Saa adderer du til din main function dette: System.AppDomain.CurrentDomain.AppendPrivatePath(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), pathToDllPlugins));
Og sidst med ikke mindst dette:
foreach(string file in System.IO.Directory.GetFiles(pathToDllPlugins, "*.dll")) { try { System.IO.FileInfo fi = new System.IO.FileInfo(file); string filename = fi.Name.Replace(System.IO.Path.GetExtension(file), "");
System.Reflection.Assembly ass = AppDomain.CurrentDomain.Load(System.IO.Path.GetFileNameWithoutExtension(filename)); //System.Reflection.Assembly.Load(); foreach(System.Type type in ass.GetTypes()) { if(type.ToString() == "ITest") continue;
Ok....det ser fornuftigt. Desværre troede jeg lige jeg var så langt med mit system, men jeg har et mega problem med at loade mine plugins, brugte et eksempel fra c-sharpcorner og modificerede det og har nu problemer med at finde den rigtige Type således jeg kan loade min Assembly. Får hele tiden en fejl der hedder:
System.NullReferenceException: Object reference not set to an instance of an object.at CollaborationTool.ModuleHandler.loadModules()
Her forsøger jeg at udskrive navnet på typen jeg netop har loadet, min kode ser således ud: INTERFACE:
public Int32 Add(Int32 a, Int32 b) {return a + b;}
public string Name {get{return "m_strName";}set{m_strName=value;}}
public IPluginHost Host { get{return m_Host;} set { m_Host=value; m_Host.Register(this); } } } }
Jeg kan ikke gennemskue hvad fejlen er, den kommer i aktiveringen hvor jeg forsøger at udskrive hele navnet til konsollen. Jeg kommer aldrig ind i næste if sætning da mit ojbType er null
Uden at have proevet det, er du saa sikker paa at typenavnet er det rigtige, proev at skriv alle typenavnene ud via GetNames(tror jeg det hedder). Lav en iteration, og du vil faa de korrekte navne
Det hjalp gevaldigt, nu har jeg et problem med InvalidCastException i linien myPlugin = (IPlugin)Activator.CreateInstance(objtype); myPlugin er af typen IPlugin, som er et interface i PlugIn namespace....og som sagt har jeg ikke modificeret noget på originalkoden, så jeg kan ikke helt lige finde fejlen.
Ja, nu har jeg lige arbejdet med det her, og det virker fint paa min maskine. Jeg kan ikke se hvad det er der skulle fejle. En ting som jeg syntes er lidt irreterende er at du kalder et namespace det samme som en klasse. Det kan virke lidt forvirende. Proev foelgende(samme fil):
namespace CollaborationTool { /// <summary> /// Summary description for ModuleHandler. /// </summary> public class ModuleHandler {
public void loadModules() { foreach(System.Type type in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()) System.Diagnostics.Debug.WriteLine(type.ToString()); /* Console.WriteLine("Test # 1"); Assembly myAssembly=Assembly.Load("Dynamic"); Console.WriteLine("Test # 2"); Type objtype=null; Console.WriteLine("Test # 3");
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.