2 Stimmen

Plugin-Architektur mit Interfaces; Interface-Prüfung funktioniert nicht

Ich implementiere eine einfache Plugin-Architektur in einer Anwendung. Die Plugin-Anforderungen werden über eine Schnittstelle (IPlugin) definiert, die sich in einer *.dll befindet, die von der Anwendung und dem Plugin referenziert wird. Die Anwendung verfügt über einen Plugin-Manager (ebenfalls in derselben *.dll), der die Plugins lädt, indem er nach allen *.dlls in einem Plugin-Ordner sucht, sie lädt und dann überprüft, ob das Plugin die Schnittstelle implementiert. Ich habe diese Überprüfung auf zwei verschiedene Arten durchgeführt [zuvor durch ein einfaches if (plugin is IPlugin)], aber keine davon erkennt, wenn ein Plugin die Schnittstelle implementiert. Hier ist der Code:

Assembly pluginAssembly = Assembly.LoadFrom(currFile.FullName);
if (pluginAssembly != null)
{
    foreach (Type currType in pluginAssembly.GetTypes())
    {
        if (currType.GetInterfaces().Contains(typeof(IPlugin)))
        {
            // Code here is never executing
            // even when the currType derives from IPlugin
        }
    }                    
}

Früher testete ich einen bestimmten Klassennamen ("Plugin"), aber dann ließ ich zu, dass er alle Klassen in der Assembly durchlief, ohne Erfolg. (Dies folgt einem Beispiel, das ich an anderer Stelle gefunden habe.) Um die Sache etwas komplizierter zu machen, gibt es zwei Schnittstellen, von denen jede die ursprüngliche Schnittstelle implementiert (IPluginA, IPluginB). Das Plugin implementiert eigentlich eine der spezifischeren Schnittstellen (IPluginB). Ich habe es jedoch mit dem Plugin versucht, das nur die allgemeinere Schnittstelle (IPlugin) implementiert, und das funktioniert immer noch nicht.

[Bearbeiten: als Antwort auf die beiden Antworten, die ich zuerst erhalten habe] Ja, ich habe versucht, IsAssignableFrom zu verwenden. Siehe das Folgende:

Assembly pluginAssembly = Assembly.LoadFrom(currFile.FullName);
if (pluginAssembly != null)
{
    foreach (Type currType in pluginAssembly.GetTypes())
    {
        if (typeof(IPlugin).IsAssignableFrom(currType))
        {
            string test = "test";
        }
    }
}

5voto

Sam Harwell Punkte 94511

Haben Sie es schon versucht?

typeof(IPlugin).IsAssignableFrom(currType)

Außerdem, Typen implementieren Schnittstellen, aber sie haben keine ableiten. von ihnen. Die BaseType Eigentum und IsSubclassOf Methode zeigen Ableitung, wobei IsAssignableFrom zeigt die Ableitung oder Umsetzung.

Bearbeiten: Sind Ihre Versammlungen unterzeichnet? Sie könnten geladen werden nebeneinanderliegende Versionen Ihrer Baugruppe und da Type Objekte werden verglichen mit ReferenceEquals Der gleiche Typ in zwei nebeneinander angeordneten Baugruppen wäre völlig unabhängig.

Bearbeiten 2: Versuchen Sie dies:

public Type[] LoadPluginsInAssembly(Assembly otherAssembly)
{
    List<Type> pluginTypes = new List<Type>();
    foreach (Type type in otherAssembly.GetTypes())
    {
        // This is just a diagnostic. IsAssignableFrom is what you'll use once
        // you find the problem.
        Type otherInterfaceType =
            type.GetInterfaces()
            .Where(interfaceType => interfaceType.Name.Equals(typeof(IPlugin).Name, StringComparison.Ordinal)).FirstOrDefault();

        if (otherInterfaceType != null)
        {
            if (otherInterfaceType == typeof(IPlugin))
            {
                pluginTypes.Add(type);
            }
            else
            {
                Console.WriteLine("Duplicate IPlugin types found:");
                Console.WriteLine("  " + typeof(IPlugin).AssemblyQualifiedName);
                Console.WriteLine("  " + otherInterfaceType.AssemblyQualifiedName);
            }
        }
    }

    if (pluginTypes.Count == 0)
        return Type.EmptyTypes;

    return pluginTypes.ToArray();
}

2voto

Francis B. Punkte 6776

Die Methode IsAssignableFrom ist das, wonach Sie suchen:

Type intType = typeof(IInterface);
foreach (Type t in pluginAssembly.GetTypes())
{
    if (intType.IsAssignableFrom(t))
    {
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X