Reputation: 938
I'm trying to create some code that detects all concrete implementations of an interface within c#. However I dont believe the problem I am facing is confined to c# and is a general oop question.
I want to do the detection at runtime so I have the ability to expand the implementations of the interface at a future date.
What options/approaches are available to me in order to achieve this?
for example
public interface IAnimal{
void MakeNoise();
}
public class Dog : IAnimal{
public void MakeNoise()
{
Console.WriteLine("WOOF");
}
}
public class Cat : IAnimal{
public void MakeNoise()
{
Console.WriteLine("Meow");
}
}
public class AnimalInstanceController{
/*Im trying to populate this with all classes that implement IAnimal
*/
public IEnumerable<IAnimal> {get;set;}
}
Thanks
Nicholas
Upvotes: 1
Views: 296
Reputation: 5679
You can relatively easily do this using reflection, eg:
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var allTypes = assemblies.SelectMany(x => x.GetTypes());
var implTypes = allTypes.Where(t => !t.IsInterface && !t.IsAbstract)
.Where(t => typeof (IAnimal).IsAssignableFrom(t));
var animals = implTypes.Select(t => (IAnimal) Activator.CreateInstance(t))
.ToArray();
However there are a number of concerns:
I would suggest looking at a dependency injection / inversion of control container such as Castle Windsor along with automatic registration, eg:
container.Register(AllTypes.FromAssemblyContaining<IAnimal>().BasedOn<IAnimal>());
There are various options of specifying which assemblies to scan, and if you use installers, you can make your system quite extensible.
Upvotes: 1
Reputation: 38179
You could do something like the following:
var implementations = new List<Type>();
foreach (Assembly assembly in <collection of assemblies you want to scan>)
{
foreach (Type type in assembly.GetTypes())
{
if (type.GetInterfaces().Contains(typeof(IAnimal)))
{
implementations.Add(type);
}
}
}
Or use a DI container like Autofac
Upvotes: 4
Reputation: 62246
You can use Type.IsAssignableFrom information of a concrete type's implementation to see if it implements an interface (can be assigned to it so).
The good consise implementation can be like this:
var type = typeof(IMyInteraface);
var types = AppDomain.CurrentDomain.GetAssemblies().ToList()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
which you can find in accepted answer of: Getting all types that implement an interface
This is naturally looks only into a types of a current domain.
Upvotes: 0
Reputation: 2454
I could see how you could do this using reflection - going through from an assembly to its classes, then interrogating each to see if it could be cast to IWhatever - but of course this approach while not c#-specific is certainly .net-specific.
Any use to you?
Upvotes: 0