Avatar billede brian0905 Nybegynder
16. juni 2003 - 15:04 Der 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???
Avatar billede Lasse Novice
16. juni 2003 - 19:28 #1
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;

                        ITest itest = (ITest)Activator.CreateInstance(type);
                        this.Menu.MenuItems.add(itest.GetMenuItem());


Ja, noget af det er pseudo kode, men du kan sikkert godt se ideen.

                    }
                }
                catch(System.Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(ex.Message);
                }
            }
Avatar billede brian0905 Nybegynder
16. juni 2003 - 20:34 #2
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:

using System;

namespace PlugIn
{
    /// <summary>
    /// Generic plugin interface
    /// </summary>
    public interface IPlugin
    {
        Int32 Add(Int32 a, Int32 b);
        string Name{get;set;}
        IPluginHost Host{get;set;}
    }

    /// <summary>
    /// The host
    /// </summary>
    public interface IPluginHost
    {
        bool Register(IPlugin ipi);
    }
}

AKTIVERING AF ASSEMBLY:
using System;
using System.Reflection;
using PlugIn;

namespace CollaborationTool
{
    /// <summary>
    /// Summary description for ModuleHandler.
    /// </summary>
    public class ModuleHandler : IPluginHost
    {
       
        public void loadModules()
        {
            Console.WriteLine("Test # 1");
            Assembly myAssembly=Assembly.Load("Dynamic");
            Console.WriteLine("Test # 2");
            Type objtype=myAssembly.GetType("Dynamic.PlugIn");
            Console.WriteLine("Test # 3");
            IPlugin myPlugin;
            Console.WriteLine("Test # 4");
            try
            {
                //myAssembly=Assembly.Load("Dynamic");
                Console.WriteLine("Test # 5");
                if(myAssembly!=null)
                {
                    Console.WriteLine("Test # 6");
                    objtype=myAssembly.GetType("ColaborationTool.PlugIn");
                    Console.WriteLine(objtype.FullName);
                    Console.WriteLine("Test # 7");
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("Test # 8");
                Console.WriteLine("der opstod en fejl: "+e);
                Console.WriteLine("Test # 9");
            }
            try
            {
                if (objtype != null)
                {
                    Console.WriteLine("Test # 10");
                    myPlugin = (IPlugin)Activator.CreateInstance(objtype);
                    Console.WriteLine("Test # 11");
                    myPlugin.Host = this;
                    Console.WriteLine("Test # 12");
                    Console.WriteLine("myPlugin.Add(1,2)=" + myPlugin.Add(1,2));
                    Console.WriteLine("Test # 13");
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("der opstod en fejl: "+e);
            }

        }

        public bool Register(IPlugin ipi)
        {
            Console.WriteLine("Registered: " + ipi.Name);
            return true;
        }
    }
}

SELVE MIT PLUGIN:
using System;
using PlugIn;

namespace Dynamic
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class PlugIn : IPlugin
    {
        private string m_strName;
        private IPluginHost m_Host;
       
        public string getName()
        {
            return "Brian";
        }

        public PlugIn()
        {
            m_strName = "hello I'm " + ToString();
        }
       
        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
Avatar billede Lasse Novice
16. juni 2003 - 21:20 #3
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
Avatar billede brian0905 Nybegynder
16. juni 2003 - 21:32 #4
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.
Avatar billede brian0905 Nybegynder
16. juni 2003 - 21:35 #5
Åååh ja og objtype er at typen "Dynamic.PlugIn", det burde være muligt at caste direkte til dette interface
Avatar billede Lasse Novice
16. juni 2003 - 21:37 #6
har du fundet fejlen, eller hvad er den sidste kommentar for noget?
Avatar billede brian0905 Nybegynder
16. juni 2003 - 21:43 #7
Nope har ikke fundet den invalid cast fejl.....desværre :-( har du et godt råd (lav det lige som et svar så du kan få nogle points)
Avatar billede Lasse Novice
16. juni 2003 - 21:56 #8
kan du ikke lige poste dit indtil videre faerdige program del igen.,
Avatar billede brian0905 Nybegynder
16. juni 2003 - 22:05 #9
Klassen der aktiverer:

using System;
using System.Reflection;
using PlugIn;

namespace CollaborationTool
{
    /// <summary>
    /// Summary description for ModuleHandler.
    /// </summary>
    public class ModuleHandler : IPluginHost
    {
       
        public void loadModules()
        {
            Console.WriteLine("Test # 1");
            Assembly myAssembly=Assembly.Load("Dynamic");
            Console.WriteLine("Test # 2");
            Type objtype=null;
            Console.WriteLine("Test # 3");
            IPlugin myPlugin;
            Console.WriteLine("Test # 4");
            try
            {
                Console.WriteLine("Test # 5");
                if(myAssembly!=null)
                {
                    Console.WriteLine("Test # 6");
                    objtype=myAssembly.GetType("Dynamic.PlugIn");
                    Console.WriteLine("Test # 7");
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("Test # 8");
                Console.WriteLine("der opstod en fejl: "+e);
                Console.WriteLine("Test # 9");
            }
            try
            {
                if (objtype != null)
                {
                    Console.WriteLine("Test # 10");
                    Console.WriteLine(objtype.FullName);
                    myPlugin = (IPlugin)Activator.CreateInstance(objtype);
                    Console.WriteLine("Test # 11");
                    myPlugin.Host = this;
                    Console.WriteLine("Test # 12");
                    Console.WriteLine("myPlugin.Add(1,2)=" + myPlugin.Add(1,2));
                    Console.WriteLine("Test # 13");
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("der opstod en fejl: "+e);
            }

        }

        public bool Register(IPlugin ipi)
        {
            Console.WriteLine("Registered: " + ipi.Name);
            return true;
        }
    }
}

Interfaces:

using System;

namespace PlugIn
{
    /// <summary>
    /// Generic plugin interface
    /// </summary>
    public interface IPlugin
    {
        Int32 Add(Int32 a, Int32 b);
        string Name{get;set;}
        IPluginHost Host{get;set;}
    }

    /// <summary>
    /// The host
    /// </summary>
    public interface IPluginHost
    {
        bool Register(IPlugin ipi);
    }
}

Et plugin:

using System;
using PlugIn;

namespace Dynamic
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class PlugIn : IPlugin
    {
        private string m_strName;
        private IPluginHost m_Host;
       
        public PlugIn()
        {
            m_strName = "hello I'm " + ToString();
        }
       
        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);
            }
        }
    }
}

Noget der undrer mig, er at den loader begge mine assemblies (både mit interface og mit plugin, kan det tænkes at det er her fejlen sker???
Avatar billede Lasse Novice
16. juni 2003 - 22:20 #10
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");
           
            Console.WriteLine("Test # 4");
            try
            {
                Console.WriteLine("Test # 5");
                if(myAssembly!=null)
                {
                    Console.WriteLine("Test # 6");
                    objtype=;
                    Console.WriteLine("Test # 7");
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("Test # 8");
                Console.WriteLine("der opstod en fejl: "+e);
                Console.WriteLine("Test # 9");
            }
            */
            try
            {
                PlugIn2.IPlugin myPlugin;
                Console.WriteLine("Test # 10");
                myPlugin = (PlugIn2.IPlugin)Activator.CreateInstance(System.Reflection.Assembly.GetExecutingAssembly().GetType("Dynamic.PlugIn"));
                Console.WriteLine("Test # 11");
                Console.WriteLine("Test # 12");
                Console.WriteLine("myPlugin.Add(1,2)=" + myPlugin.Add(1,2));
                Console.WriteLine("Test # 13");

            }
            catch(Exception e)
            {
                Console.WriteLine("der opstod en fejl: "+e);
            }

        }

        public bool Register(PlugIn2.IPlugin ipi)
        {
            Console.WriteLine("Registered: " + ipi.Name);
            return true;
        }
    }
}

namespace PlugIn2
{
    /// <summary>
    /// Generic plugin interface
    /// </summary>
    public interface IPlugin
    {
        Int32 Add(Int32 a, Int32 b);
        string Name{get;set;}
    }
}

namespace Dynamic
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class PlugIn : PlugIn2.IPlugin
    {
        private string m_strName;
       
        public PlugIn()
        {
            m_strName = "hello I'm " + ToString();
        }
       
        public Int32 Add(Int32 a, Int32 b)
        {return a + b;}
       
        public string Name
        {get{return m_strName;}set{m_strName=value;}}

    }
}


i main:

CollaborationTool.ModuleHandler mh = new CollaborationTool.ModuleHandler();
            mh.loadModules();
Avatar billede brian0905 Nybegynder
16. juni 2003 - 22:26 #11
Fedt!! Det virker... bare namespaces!!!! :-|
Avatar billede Lasse Novice
16. juni 2003 - 22:41 #12
godt at hoere
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester