Reputation: 424
Yes, there are similar questions, but none of them solved my problem. I created a new solution with three projects:
The ICrawler.cs code:
namespace Shared.Data.Structures
{
public interface ICrawler
{
void SayHello();
}
}
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");
}
}
}
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;
}
}
}
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
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