Laden...

[gelöst] Plugins mittel MEF realisieren?

Erstellt von Tactive vor 13 Jahren Letzter Beitrag vor 13 Jahren 1.665 Views
T
Tactive Themenstarter:in
29 Beiträge seit 2007
vor 13 Jahren
[gelöst] Plugins mittel MEF realisieren?

Hallo,

ich versuche gerade ein Plugin-System auf Basis von MEF aufzubauen, was aber leider nicht so ganz klappen will. Vielleicht ist das was ich vorhabe mit MEF auch nicht zu realisieren, daher wäre ich über ein paar Hinweise sehr dankbar.

Ich habe zunächst angefangen, mir einen MEFHost zu Basteln der folgende Schnittstelle definiert:


    public interface ITest
    {
        void SayHello(string message);
    }

Im Programmcode des Host-Projekte habe ich mir dann folgendes, aus diversen Tutorials, zusammengereimt:


    public class Program
    {
        [Import]
        public IEnumerable<ITest> Tests { get; set; }

        public static void Main(string[] args)
        {
            var p = new Program();
            p.Run();
            Console.ReadLine();
        }

        public void Run()
        {
            Compose();
        }

        private void Compose()
        {
            var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var container = new CompositionContainer(catalog);
            var batch = new CompositionBatch();
            batch.AddPart(this);
            container.Compose(batch);
        }
    }

Und finally habe ich ein MEFClient Projekt erstellt, welches als DLL kompiliert und nur eine Klasse enthält welche dann ITest implementiert:


    [Export]
    public class TestClass1 : ITest
    {
        public void SayHello(string message)
        {
            Console.WriteLine(">> TestClass1: " + message);
        }
    }

Compiliert auch wunderbar aber funktioniert leider überhaupt nicht. Er wirft in der Zeile wo das container.Compose() aufgerufen wird eine Fehlermeldung die mir auch nicht weiterhilft.

Weiss hier jemand ob das was ich vorhabe geht und was ich verkehrt mache???

Vielen dank schonmal für Eure Unterstützung.

P.s.: Weiss hier zufällig ob das MEF auch mit Probing klarkommt, als ob ich die Client-Datei auch in einem untergeordneten Verzeichnis ablegen kann??

6.862 Beiträge seit 2003
vor 13 Jahren

Hallo,

gleich vorneweg - das sind keine Plugins sondern Extensions/Parts. Das macht einen Unterschied da MEF praktisch den Extension Code mit dem Hauptprogramm merged, während Plugins im klassischen Sinne ja isoliert vom Hauptprogramm laufen. Wenn man sich Gedanken macht um Entladbarkeit, Prozessisolierung etc. muss man das bedenken.

Dann noch unbedingt [Hinweis] Wie poste ich richtig? Punkt 5 beachten.

Er wirft in der Zeile wo das container.Compose() aufgerufen wird eine Fehlermeldung die mir auch nicht weiterhilft. Uns auch nicht wenn du sie nicht postest 😃

Nun zum Problem: Du fügst nur deine Hauptassembly zum CompositionContainer hinzu, wie soll er da jemals in der Dll die Extension finden? Es macht auch keinen Sinn das Interface im Hostprogramm zu definieren da ja jede Extensions dann darauf referenzieren müsste und das ist ja nicht wirklich Sinn der Sache. Besser ist eine Assembly in der du die gemeinsamen Interfaces auslagerst und worauf dann Host und Extensions zugreifen.

Zu der Frage nach dem Unterordner, welche im Prinzip auch dein jetziges Problem löst - es gibt nicht nur nen AssemblyCatalog. Schau dir an was es da noch so gibt und dann kriegst du deine Probleme auch in den Griff.

Baka wa shinanakya naoranai.

Mein XING Profil.

T
Tactive Themenstarter:in
29 Beiträge seit 2007
vor 13 Jahren

Hallo Talla,

vielen Dank für die Hinweise, die mir doch weitergeholfen haben und ich konnte mein Problem dann auch lösen. Sieht in der Host-Klasse nun so aus (falls noch jemand wissen will wie es geht):


    public class Program
    {
        [ImportMany(typeof(ITest))]
        private IEnumerable<ITest> tests;

        public static void Main(string[] args)
        {
            var p = new Program();
            p.Run();
            Console.ReadLine();
        }

        public void Run()
        {
            Compose();

            foreach (var op in tests)
                op.SayHello("Hello MEF");
        }

        private void Compose()
        {
            var catalog = new AggregateCatalog();
            var location = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            catalog.Catalogs.Add(new DirectoryCatalog(location));
            var container = new CompositionContainer(catalog);
            container.SatisfyImportsOnce(this);
        }
    }

Dabei kann natürlich auch container.GetExports<T>() verwendet werden. Die Client-Klasse habe ich ebenfalls geringfügig geändert:


    [Export(typeof(ITest))]
    public class TestClass1 : ITest
    {
        public void SayHello(string message)
        {
            Console.WriteLine(">> TestClass1: " + message);
        }
    }

Wichtig sind also die Typ-Angaben was man exportiert bzw. importiert. In vielen Dokumenationen und Tutorials (die teilweise 2-3 Jahre alt sind), wird darauf leider nicht hingewiesen. Lange Reder, überhaupt kein Sinn, wenn man erstmal weiss wie es geht isses total simpel (bis zum nächsten Problem).

Vielen Dank nochmal.

P.s.: Ja, das nächste mal Poste ich dann auch die Fehlermeldung. Habs diesmal vergessen.

190 Beiträge seit 2005
vor 13 Jahren
1.044 Beiträge seit 2008
vor 13 Jahren

Hallo Tactive,

TestClass1 exportiert auf den Contract ITest nicht. D.h. wird auch nichts gefunden. Lies dich mal in das Thema "Contracts" ein. MEF lässt sich auch Debuggen. Auf den Seiten von CodePlex(mef.codeplex.com) findest du über das Thema Debugging ein eigenes Kapitel. Das sollte dir weiterhelfen. Schau dir mal das Tool MEFX an.

zero_x