Justin
Justin

Reputation: 18186

Using reflection to get all classes of certain base type in dll

I have a dll that contains a number of classes that all inherit from a CommandBase class. I'm trying to get instances of all of these classes (CommandA, CommandB, CommandC, etc...) using reflection in C# so that I can call a specific method on each one. Here is what I have so far:

//get assemblies in directory.
string folder = Path.Combine(HttpContext.Current.Server.MapPath("~/"), "bin");
var files = Directory.GetFiles(folder, "*.dll");
//load each assembly.
foreach (string file in files)
{
  var assembly = Assembly.LoadFile(file);
  if (assembly.FullName == "MyCommandProject")
  {
    foreach (var type in assembly.GetTypes())
    {
      if (!type.IsClass || type.IsNotPublic) continue;
      if(type is CommandBase)
      {
        var command = Activator.CreateInstance(type) as CommandBase;
      }
    }
  }
}

I'm having 2 issues. The 1st issue is that the line "if(type is CommandBase") gives the following warning:

The given expression is never of the provided type CommandBase.

The 2nd issue is that I can't figure out how to get an instance of the actual object (CommandA, CommandB, etc...), just converting it to CommandBase isn't enough.

Upvotes: 21

Views: 36184

Answers (4)

Jeff Sheldon
Jeff Sheldon

Reputation: 2094

This is the method I use to load up based on an interface.

private 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();
}

And here's the same function that pulls back based on base class.

private static IList<T> GetInstances<T>()
{
        return (from t in Assembly.GetExecutingAssembly().GetTypes()
                       where t.BaseType == (typeof(T)) && t.GetConstructor(Type.EmptyTypes) != null
                       select (T)Activator.CreateInstance(t)).ToList();
}

Of course it would need to be modified slightly to point at the reference you're loading.

Upvotes: 32

Akash Kava
Akash Kava

Reputation: 39916

You must change

if(type is CommandBase) 

to

if(type.IsSubclassOf(typeof(CommandBase)))

If the IsSubclassOf is the converse of IsAssignableFrom. That is, if t1.IsSubclassOf(t2) is true, then t2.IsAssignableFrom(t1) is also true.

Upvotes: 9

Jess
Jess

Reputation: 42928

That's because your type variable is a Type, not a CommandBase.

You want

if(type == typeof(CommandBase))

(Thanks Greg for the correction)

Upvotes: 2

Dr. Wily&#39;s Apprentice
Dr. Wily&#39;s Apprentice

Reputation: 10280

Change type is CommandBase to typeof(CommandBase).IsAssignableFrom(type)

Upvotes: 8

Related Questions