To avoid those repetitive codes that 'registers' types of a class or interface you can use a bit of reflection and dynamically find and instantiate those.
First, list all the types (GetTypes) from the current assembly (GetExecutingAssembly):
var types = Assembly.GetExecutingAssembly().GetTypes();
Then filter by whatever type you want with IsAssignableFrom:
var filteredTypes = types.Where(t => typeof(MyType).IsAssignableFrom(t));
And lastly instantiate those with the good old Activator.CreateInstance:
var instances = filteredTypes.Select(t => (MyType)Activator.CreateInstance(t));
Below goes a working example of such approach. Note that there are many potential edge cases in play here, patch the code accordingly to your needs.
using System;
using System.Linq;
using System.Reflection;
// No "class Program" or "static void Main"
// C# 9 top-level statements!
// Watch out for some potential pitfalls of using Activator.CreateInstance such as:
// - runtime error when class doesn't have a parameterless constructor
// - can be a costly method call
static T Instantiate<T>(Type t) => (T)Activator.CreateInstance(t);
static bool IsGreeter(Type t) => typeof(IGreeter).IsAssignableFrom(t) && t.IsClass;
// Use AppDomain.CurrentDomain.GetAssemblies() for other assemblies than the current one
var types = Assembly.GetExecutingAssembly().GetTypes().Where(IsGreeter);
var instances = types.Select(Instantiate<IGreeter>);
// Prints:
// "Hello, I'm Anna."
// "Hi, Joe here."
// "Woof!"
foreach (var i in instances)
i.Greeting();
public interface IGreeter
{
void Greeting();
}
public class Anna : IGreeter
{
public void Greeting() => Console.WriteLine("Hello, I'm Anna.");
}
public class Joe : IGreeter
{
public void Greeting() => Console.WriteLine("Hi, Joe here.");
}
public class Dog : IGreeter
{
public void Greeting() => Console.WriteLine("Woof!");
}
Top comments (0)