Laden...

Wie entwickle ich ein Plugin-System mit Dependency Injection?

Erstellt von BlackMatrix vor 6 Jahren Letzter Beitrag vor 6 Jahren 1.557 Views
B
BlackMatrix Themenstarter:in
218 Beiträge seit 2012
vor 6 Jahren
Wie entwickle ich ein Plugin-System mit Dependency Injection?

Hallo.

Ich möchte mir ein Plugin-System zusammenbauen bei dem ich Funktionalität hinzufügen kann. Da stellt sich mir die Frage wie man das unter heutigen Gesichtspunkten entwickelt? Ich habe viel über Dependency Injection gelesen und bin mir ziemlich sicher, dass das auch da Anwendung findet. Jedoch lass ich mich gerne eines besseren Belehren.

Ich habe mir das wie folgt gedacht:


using Microsoft.Extensions.DependencyInjection;
// ...

namespace Bootstrapper
{
    internal class Program
    {
        private static void Main()
        {
            var serviceCollection = new ServiceCollection();

            foreach (var plugin in LoadPlugins())
            {
                plugin.Initialize(serviceCollection);
            }

            var provider = serviceCollection.BuildServiceProvider();

            foreach (var activity in provider.GetServices<IActivity>())
            {
                activity.Execute();
            }
        }

        private static IEnumerable<IPlugin> LoadPlugins()
        {
            return Directory
                .EnumerateFiles("Plugins", "*.dll")
                .Select(LoadPlugin<IPlugin>);
        }

        public static T LoadPlugin<T>(string path)
        {
            var assembly = Assembly.LoadFrom(path);

            foreach (var type in assembly.GetExportedTypes())
            {
                if (type.GetInterfaces().Contains(typeof(T)))
                {
                    return (T)Activator.CreateInstance(type);
                }
            }

            return default(T);
        }
    }
}


    namespace PluginAScope
    {
        public class PluginA : IPlugin
        {
            public void Initialize(IServiceCollection serviceCollection)
            {
                serviceCollection.AddSingleton<IActivity, ActivityA>();
            }
        }

        public class ActivityA : IActivity
        {
            public void Execute()
            {
                Console.WriteLine("ActivityA");
            }
        }
    }


    namespace PluginBScope
    {
        public class PluginB : IPlugin
        {
            public void Initialize(IServiceCollection serviceCollection)
            {
                serviceCollection.AddSingleton<IActivity, ActivityB>();
            }
        }

        public class ActivityB : IActivity
        {
            public void Execute()
            {
                Console.WriteLine("ActivityB");
            }
        }
    }


    namespace Contracts
    {
        public interface IPlugin
        {
            void Initialize(IServiceCollection serviceCollection);
        }

        public interface IActivity
        {
            void Execute();
        }
    }

Wie ist das zu bewerten? Ist das so angedacht? Gibt es vielleicht auch schon komplette Frameworkx, die da einem noch weitere Arbeit abnehmen? Ich entwickle als NETStandard Bibliothek, daher auch die Microsoft.Extensions.DependencyInjection Abhängigkeit. Ist ein ServiceLocator das gleiche wie ein ServiceProvider in diesem Namespace? Welche Services lege ich dann alle in den ServiceProvider, alle Datenbankservices, alle ViewModels, einfach alles? Glaube das wäre es erstmal 😃

Vielen Dank für eure Antworten.

16.834 Beiträge seit 2008
vor 6 Jahren

Es gibt nicht das Pluginsystem.

Welche Anforderungen hast Du an das System, wo soll es zu welchem Zweck eingesetzt werden?

1.029 Beiträge seit 2010
vor 6 Jahren

Hi,

also ein DependencyInjection würde ich eher ein Requirement für ein PluginSystem nennen - du wirst es gebrauchen können - aber es ist kein PluginSystem.

Als Plugin-System von Microsoft kenne ich 2 Sachen:

  1. MEF - wird z.B. auch von SSMS und VS benutzt - recht einfach und flexibel - lädt jedoch alles in die selbe AppDomain. (Letzteres ist nicht nur schlecht - hat Vor- und Nachteile)

  2. System.Addin - ist deutlich aufwändiger in der Entwicklung - aber auch entsprechend flexibel - so hast du z.B. auch die Möglichkeit Addins in eine andere AppDomain zu laden, womit sofern ein Addin einen Absturz verursacht nicht zwangsweise deine App mit abrauscht.

Das sind zumindest die beiden Möglichkeiten im Framework.

LG