2016-11-13 27 views
0

是的,有類似的問題,但是他們都沒有解決我的問題。我創建了三個項目新的解決方案:C# - 將對象轉換爲接口時出錯

  • FirstPlugin:圖書館項目,編譯成DLL。
  • MainApp:控制檯應用程序,將導入FirstPlugin。
  • 共享:聲明接口的共享項目。 FirstPluginMainApp項目有它的這個項目的參考。

共享項目

項目結構:

Shared Project Structure

的ICrawler.cs代碼:

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

FirstPlugin項目

項目結構:

FirstPlugin Structure

的FP.cs代碼:

using System; 
using Shared.Data.Structures; 

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

MainApp項目

項目結構:

MainApp Project Structure

的Program.cs中的代碼:

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; 
     } 
    } 
} 

的錯誤

我得到這個漂亮和美麗的錯誤:

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

在此行中(Program.cs中):

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

我決定創建這個解決方案並複製粘貼確切的GenericPluginLoader來源(來自MSDN)。

我正在處理的項目有不同的代碼,但會發生相同的錯誤。

這段代碼有什麼問題?

我生成輸出:

  • d:\ PluginTest \模塊\ FirstPlugin.dll
  • d:\ PluginTest \ MainApp。EXE

PS:英語不是我的母語,所以...你知道(╭☞͠°͟ʖ°)╭☞。

+0

檢查程序集的「Debug,Windows,Modules」中加載了多少個副本。 – SLaks

回答

5

共享項目將其源文件直接編譯到引用它們的每個項目中。

因此,您有兩個ICrawler接口,每個接口中有一個接口,它們不是相同的類型(儘管它們是相同的)。

您試圖將新實例強制轉換爲未實現的接口的副本;你不能那樣做。

您應該使用普通的類庫,而不是共享的項目。