mardi 20 janvier 2015

c# - Different types when loading from assembly using reflection

I have a solution with 3 projects: 1) A GUI executable 2) A Class library with an containing a public API and a public interface 3) A Class library of a class that implements the above interface


I'm trying to implement a resource loader in the API, so that when the GUI calls method API.Foo() I go over every assembly inside a specific folder (found at: .\resources) which contains a copy of the assemblies I compiled (#3). Then I want to add the resource to a list and use this list to call a function that is a part of the interface (which every resource implements)


So what I've done is:



private List<IResource> m_resources;

public void Foo()
{
string resourceDir = Directory.GetCurrentDirectory() + @"\Resources";
m_resources= new List<IResource>();
foreach (var dllFile in Directory.EnumerateFiles(resourceDir))
{
IResource dllInstance;
if (TryLoadingDLL(Path.Combine(resourceDir, dllFile), out dllInstance))
{
resources.Add(dllInstance);
}
}
}

private static bool TryLoadingDLL(string dllFullPath, out IResource instanceOfDll)
{
instanceOfDll = null;
try
{
Assembly assembly = Assembly.LoadFrom(dllFullPath);
Assembly IResourceAssambly = Assembly.LoadFrom(@"C:\MyProject\MyAPI.dll");
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
var interfaces = type.GetInterfaces();
var typeOfIResource = IResourceAssambly.GetType("MyProject.IResource");
if (interfaces.Any())
{
var interfaceType = interfaces[0]; //In debuger they have the same GUID
if (interfaceType.IsEquivalentTo(typeOfIResource)) //also tried ==
{
instanceOfDll = Activator.CreateInstance(type) as IResource;
return true;
}
}
}
}
catch (Exception e)
{
Console.Error.WriteLine("Failed to load dll {0}, exception: {1}",dllFullPath, e.Message);
return false;
}
return false;
}


Iv'e actually used this at first which gave the same result:



List<Type> derivedTypesList = typses.Where(type => type.GetInterfaces().Contains(IWNAssambly.GetType("MyProject.IResource"))).ToList();
if (derivedTypesList.Count > 0)
{
instanceOfDll = (IResource)Activator.CreateInstance(derivedTypesList[0]);
return true;
}


but then I broke it down so I can debug it easily.


When I run any of these snippets, I Indeed find 1 type that implements the interface, but when I try to cast it I get null via the as operator and an exception when casting with (IResource). The exception is:



{System.InvalidCastException: Unable to cast object of type 'MyProject.MyFirstResource' to type 'MyProject.IResource'.


at ...


The problem looked like it was coming from the types so I tried replacing



var typeOfIResource = IResourceAssambly.GetType("MyProject.IResource");


with



var typeOfIResource = typeof(MyProject.IResource);


And the result was that now it didn't find anything at all, i.e the interfaceType.IsEquivalentTo(typeOfIResource) is always false. When I looked with the debugger on these types they looked exactly the same so I don't know what's the problem.


First, is this a good practice? I want other developers to supply me with their assemblies and if they implement the IResource interface then use reflection to create an instance and invoke the wanted method.


Second and more important at this time, what is the problem and how can I solve it?


Thanks!!!






Aucun commentaire:

Enregistrer un commentaire