1

I'm trying to search a specific namespace and return instances of all classes that implement the specified interface and have the specified base class.

Here is the code

private List<T> GetInstancesWithInterface<T, T2>(string @namespace) { var tList = Assembly.GetExecutingAssembly() .GetTypes() .Where(t => t.Namespace == @namespace) .Where(t => t.BaseType == (typeof (T)) && t.GetInterfaces().Contains(typeof(T2))) .Select(t => (T)Activator.CreateInstance(typeof(T), this)) .ToList(); return tList; } 

And here is the calling code

var examples = GetInstancesWithInterface<DrawableGameComponent, IResettable>("GamePhysics.Physics"); foreach (var example in examples) { Debug.Assert(example is IResettable); var r = example as IResettable; _examples.Add(r); Components.Add(example); if (Components.Count == 0) continue; example.Enabled = false; example.Visible = false; } 

The problem I am having is the Assert fails because I get back a list of DrawableGameComponent which cannot be treated as IResettable so the code var r = example as IResettable always returns null.

Additional info

I should have also mentioned that DrawableGameComponent does not implement the IResettable interface. My three example classes that I'm trying to fetch all have DrawableGameComponent as the base class and they also implement IResettable.

Additional thoughts

I was thinking that perhaps I should create a new abstract class called Example which implements DrawableGameComponent and IResettable and then my concrete example classes can just implement the Example base class. I suppose this might be better design but I am also interested to know if I can get it working as it is.

6
  • "because I get back a list of DrawableGameComponent which cannot be treated as IResettable" - I very much doubt that's the problem. The is operator should deal with such a situation just fine. Have you stepped through it with a debugger and looked at each object returned? Commented Jun 24, 2013 at 16:47
  • Yes, I've stepped through and r is always null. I should have also mentioned that DrawableGameComponent does not implement the IResettable interface. My three example classes that I'm trying to fetch all have DrawableGameComponent as the base class and they also implement IResettable. I'll update the question with this extra info too. Commented Jun 24, 2013 at 16:51
  • Have you tried (typeof (T)).IsAssignableFrom(t.BaseType) (and vice versa) rather than t.BaseType == (typeof (T))? If you're looking for T's child classes, then == most likely won't work. Commented Jun 24, 2013 at 17:05
  • @valverij Thanks for the response but I get the same result using IsAssignableFrom Commented Jun 24, 2013 at 17:10
  • 2
    What about changing the Select to Select(t => (T)Activator.CreateInstance(t, this)). The way it's currently set up will create instances of T whenever you find a child class, rather than creating instances of the child classes. Commented Jun 24, 2013 at 17:13

2 Answers 2

4

You're passing the wrong type to Activator.CreateInstance, you should change it to:

.Select(t => (T)Activator.CreateInstance(t, this)) 

you might also want to use Type.IsSubclassOf in your Where clause instead of looking at the base class directly.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Lee. @valverij already answered in his comment so I'll wait to see if he posts an answer I can accept.
Thanks for the added info about IsSubclassOf, I can see how this would be better.
3

(Posting as requested in comments. Thanks for waiting)

Take a look at the Select portion of the LINQ query:

.Select(t => (T)Activator.CreateInstance(typeof(T), this)) 

Passing typeof(T) into Activator.CreateInstance will create a new object of type T. Since you are actually looking to create objects out of your found types, you would want to change this to:

.Select(t => (T)Activator.CreateInstance(t, this)) 

This will ensure that the Activator creates instances of the types found in the previous Where.

As Lee also mentioned, using something like IsSubclassOf or IsAssignableFrom in your Where expression is preferable to a straight up == when searching for subclasses. From my experience, they work about the same, except IsAssignableFrom will also work with interfaces.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.