2016-11-13 4 views
0

Ja, es gibt ähnliche Fragen, aber keine von ihnen hat mein Problem gelöst. Ich habe eine neue Lösung mit drei Projekten:C# - Fehler beim Umwandeln des Objekts in die Schnittstelle

  • FirstPlugin: Bibliotheksprojekt, um DLL kompiliert.
  • MainApp: Konsolenanwendung, importiert FirstPlugin.
  • Gemeinsam genutzt: Gemeinsames Projekt, in dem die Schnittstelle deklariert ist. Beide FirstPlugin und MainApp Projekte haben dieses Projekt auf ihre Referenzen.

Geteilt Projekt

Die Struktur Projekt:

Shared Project Structure

Der ICrawler.cs Code:

namespace Shared.Data.Structures 
{ 
    public interface ICrawler 
    { 
     void SayHello(); 
    } 
} 

FirstPlugin Projekt

Die Projektstruktur:

FirstPlugin Structure

Der FP.cs Code:

using System; 
using Shared.Data.Structures; 

namespace FirstPlugin 
{ 
    public class FP : ICrawler 
    { 
     public void SayHello() { 
      Console.WriteLine("Hello From FirstPlugin.dll"); 
     } 
    } 
} 

MainApp Projekt

Die Projektstruktur:

MainApp Project Structure

Die Program.cs Code:

using System; 
using System.Collections.Generic; 
using System.Reflection; 
using System.IO; 
using Shared.Data.Structures; 

namespace MainApp 
{ 
    class Program 
    { 
     static void Main(string[] args) { 
      ICollection<ICrawler> plugins = GenericPluginLoader<ICrawler>.LoadPlugins(Directory.GetCurrentDirectory() + "\\modules"); 
      Console.ReadKey(); 
     } 
    } 

    public static class GenericPluginLoader<T> 
    { 
     public static ICollection<T> LoadPlugins(string path) { 
      string[] dllFileNames = null; 

      if (Directory.Exists(path)) { 
       dllFileNames = Directory.GetFiles(path, "*.dll"); 

       ICollection<Assembly> assemblies = new List<Assembly>(dllFileNames.Length); 
       foreach (string dllFile in dllFileNames) { 
        AssemblyName an = AssemblyName.GetAssemblyName(dllFile); 
        Assembly assembly = Assembly.Load(an); 

        assemblies.Add(assembly); 
       } 

       Type pluginType = typeof(T); 
       ICollection<Type> pluginTypes = new List<Type>(); 
       foreach (Assembly assembly in assemblies) { 
        if (assembly != null) { 
         Type[] types = assembly.GetTypes(); 

         foreach (Type type in types) { 
          if (type.IsInterface || type.IsAbstract) { 
           continue; 
          } 
          else { 
           if (type.GetInterface(pluginType.FullName) != null) { 

            Console.WriteLine("ICrawler name: {0}", typeof(ICrawler).AssemblyQualifiedName); 
            Console.WriteLine("Type name: {0}", type.GetInterface(pluginType.FullName).AssemblyQualifiedName); 

            /* 
             Output: 

             ICrawler name: Shared.Data.Structures.ICrawler, MainApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
             Type name: Shared.Data.Structures.ICrawler, FirstPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
            */ 

            pluginTypes.Add(type); 
           } 
          } 
         } 
        } 
       } 

       ICollection<T> plugins = new List<T>(pluginTypes.Count); 
       foreach (Type type in pluginTypes) { 
        T plugin = (T)Activator.CreateInstance(type); 
        plugins.Add(plugin); 
       } 

       return plugins; 
      } 

      return null; 
     } 
    } 
} 

Der Fehler

ich diesen netten und schönen Fehler bekommen:

Additional information: Unable to cast object of type 'FirstPlugin.FP' to type 'Shared.Data.Structures.ICrawler'

Auf dieser Linie (Program.cs):

T plugin = (T)Activator.CreateInstance(type); 

Ich entschied mich, diese Lösung zu erstellen und kopieren Sie die genaue GenericPluginLoader Quelle (von MSDN).

Das Projekt, an dem ich gerade arbeite, hat einen anderen Code, aber derselbe Fehler tritt auf.

Was ist falsch an diesem Code?

Mein Build-Ausgabe:

  • D: \ PluginTest \ Module \ FirstPlugin.dll
  • D: \ PluginTest \ MainApp.exe

PS: Englisch ist nicht meine Muttersprache, so ... Sie kennen (╭☞ ͠ ° ͟ʖ °) ╭☞.

+0

Überprüfen Sie, wie viele Kopien der Assembly in 'Debug, Windows, Modules' geladen sind. – SLaks

Antwort

5

Gemeinsame Projekte kompilieren ihre Quelldateien direkt in jedes Projekt, das auf sie verweist.

Daher haben Sie zwei ICrawler Schnittstellen, eine in jeder Baugruppe, die nicht vom gleichen Typ sind (obwohl sie identisch sind).

Sie versuchen, die neue Instanz in die Kopie der Schnittstelle zu konvertieren, die sie nicht implementiert; Das kannst du nicht tun.

Sie sollten eine normale Klassenbibliothek und kein gemeinsames Projekt verwenden.

Verwandte Themen