Reputation: 16182
Thanks to Morgano the first part of my problem was solved..
Alright, so I can do this in Java, but I'm having some problems doing it with C#..
Here's my base class (Stripped):
public abstract class Packet { }
Here's an example of my derived classes ( I have quite a few of them ):
public class Foo : Packet
{
public override void Decode(DataInputStream input)
{
throw new NotImplementedException();
}
}
After browsing stack overflow and other websites for awhile, I finally found this solution, but either it doesn't work or I'm doing something wrong.
public static List<T> GetInstances<T>()
{
return (from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetInterfaces().Contains(typeof(T))
&& t.GetConstructor(Type.EmptyTypes) != null
select (T)Activator.CreateInstance(t)).ToList();
}
Which I'm calling like this:
Console.WriteLine(PacketDecoder.GetInstances<Packet>().Count + "");
and the Count returns 0, which displays that there aren't any classes.
NOTE: I am writing all of this as a Library, so the call to GetInstaces is actually in another project, however I thought about this and moved the packet classes over to the executable project as-well and this didn't have any effect.
Upvotes: 1
Views: 232
Reputation: 70652
Your question is still not quite clear. The title says you want to find the specific types that inherit (the C# equivalent of "extends") a base type, but the code you posted actually creates instances of those types. Or, at least it would if it were correct.
The biggest issue is simply that you are calling GetInterfaces()
, but you don't seem to actually be dealing with interfaces. Instead, try this code:
static List<T> GetInstances<T>()
{
return Assembly.GetExecutingAssembly()
.GetTypes().Where(type =>
typeof(T).IsAssignableFrom(type) &&
type.GetConstructor(Type.EmptyTypes) != null)
.Select(type => (T)Activator.CreateInstance(type))
.ToList();
}
Note the use of IsAssignableFrom()
instead.
Something else to be careful about is which assembly you are inspecting. It's not clear from your post which assembly is the correct one to look in, but the Assembly
class has a few different GetXXXAssembly()
methods, each of which do different things. The "executing" assembly is not the same as the "calling" assembly is not the same as the "entry" assembly, all of which of course are not the same as an assembly identified by a type declared in that assembly.
Finally note that the above will return the base class, if it's in the same assembly you're inspecting. This may or may not be what you want, but I assume you can figure out on your own how to deal with that if it's not. :)
Upvotes: 1