Kiritonito
Kiritonito

Reputation: 424

C# - Error casting object to interface

Yes, there are similar questions, but none of them solved my problem. I created a new solution with three projects:

Shared Project

The project structure:

Shared Project Structure

The ICrawler.cs code:

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

FirstPlugin Project

The project structure:

FirstPlugin Structure

The 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 Project

The project structure:

MainApp Project Structure

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

The Error

I'm getting this nice and beautiful error:

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

On this line (Program.cs):

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

I decided to create this solution and copy paste the exact GenericPluginLoader source (from MSDN).

The project I'm working on has different code, but the same error occur.

What's wrong with this code?

My build output:

PS: English is not my native language, so... you know (╭☞ ͠° ͟ʖ °)╭☞.

Upvotes: 0

Views: 1049

Answers (1)

SLaks
SLaks

Reputation: 887305

Shared projects compile their source files directly into each project that references them.

Therefore, you have two ICrawler interfaces, one in each assembly, which are not the same type (even though they're identical).

You're trying to cast the new instance to the copy of the interface that it doesn't implement; you can't do that.

You should use a normal Class Library, not a Shared Project.

Upvotes: 6

Related Questions