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