C# - 将对象转换为接口时出错

Kir*_*ito 0 c# casting

是的,有类似的问题,但没有一个解决了我的问题.我用三个项目创建了一个新的解决方案:

  • FirstPlugin:Library项目,编译为DLL.
  • MainApp:控制台应用程序,将导入FirstPlugin.
  • 共享:声明接口的共享项目.无论FirstPluginMainApp项目有它的参考项目.

共享项目

项目结构:

共享项目结构

ICrawler.cs代码:

namespace Shared.Data.Structures
{
    public interface ICrawler
    {
        void SayHello();
    }
}
Run Code Online (Sandbox Code Playgroud)

FirstPlugin项目

项目结构:

FirstPlugin结构

FP.cs代码:

using System;
using Shared.Data.Structures;

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

MainApp项目

项目结构:

MainApp项目结构

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

错误

我收到了这个漂亮而美丽的错误:

附加信息:无法将"FirstPlugin.FP"类型的对象强制转换为"Shared.Data.Structures.ICrawler"类型

在这一行(Program.cs):

T plugin = (T)Activator.CreateInstance(type);
Run Code Online (Sandbox Code Playgroud)

我决定创建此解决方案并复制粘贴确切的GenericPluginLoader源(来自MSDN).

我正在处理的项目有不同的代码,但会出现同样的错误.

这段代码出了什么问题?

我的构建输出:

  • d:\ PluginTest \模块\ FirstPlugin.dll
  • d:\ PluginTest\MainApp.exe

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

SLa*_*aks 6

共享项目将其源文件直接编译到引用它们的每个项目中.

因此,您有两个ICrawler接口,每个接头中有一个接口,它们的类型不同(即使它们相同).

您正在尝试将新实例强制转换为它未实现的接口副本; 你不能这样做.

您应该使用普通的类库,而不是共享项目.