Reputation: 715
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.
Upvotes: 1
Views: 248
Reputation: 4951
(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.
Upvotes: 3
Reputation: 144206
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.
Upvotes: 4