mardi 15 mars 2016

Why is the Type.IsAssignableFrom method returning false here?

I've come across a strange problem using .NET reflection. Please let me know if you know why this is happening.

The requirement:

I need to generate a collection of instances of each class in a particular namespace that implements a particular interface.

Original solution:

List<IReport> allReportTypes = Assembly.GetExecutingAssembly().GetTypes().Where(
    t => !t.IsAbstract && t.IsClass && t.IsAssignableFrom(typeof(IReport)) && t.Namespace
    == @namespace).Select(t => Activator.CreateInstance(t) as IReport).ToList();

This original solution returned nothing and my question is why? Each class correctly implements the IReport interface and have been declared in the relevant Namespace. This is proven by removing the call to IsAssignableFrom:

List<IReport> allReportTypes = Assembly.GetExecutingAssembly().GetTypes().Where(
    t => !t.IsAbstract && t.IsClass && t.Namespace == @namespace).Select(t => 
    Activator.CreateInstance(t) as IReport).ToList();

This returns exactly the instances of the classes that I want, but without the check for the required interface. Note that the results of the Activator.CreateInstance method are successfully cast to the IReport interface, so the returned classes definitely implement it. I continued to play around with this issue and managed to come up with a workaround in the following query that satisfies all of my requirements.

Working solution

List<IReport> allReportTypes = Assembly.GetExecutingAssembly().GetTypes().Where(
    t => !t.IsAbstract && t.IsClass && ((TypeInfo)(t)).ImplementedInterfaces.Contains(
    typeof(IReport)) && t.Namespace == @namespace).Select(t => Activator.CreateInstance(t)
    as IReport).ToList();

However, I'd like to know why the IsAssignableFrom method is not doing what it says on the tin... er..., or in MSDN. (I've also tried the accepted solution to the other relating questions on Stack Overflow without success, so please don't suggest that I follow them).





Aucun commentaire:

Enregistrer un commentaire