Given a .Net 5 app I have multiple classes implementing an interface and I have to load one of them by its name using dependency injection.
First I created a custom attribute to mark all classes with that flag
[AttributeUsage(AttributeTargets.Class)]
public class HandlerAttribute : Attribute
{
public string Name { get; }
public HandlerAttribute(string name)
{
Name = name;
}
}
to be sure all of them implement the functionality I created an interface
public interface IHandler
{
public string GetString();
}
so one handler might look like
[HandlerAttribute("HelloWorldHandler")]
public class MyHandler : IHandler
{
public string GetString() => "Hello World";
}
All handlers should be transient services. Given the following web api controller
[ApiController]
[Route("[controller]")]
public class MyController : ControllerBase
{
[HttpGet("{handler}")]
public string Get(string handler)
{
IHandler theInjectedHandler = new MyHandler(); // get this one from the DI container by the handler name parameter
return theInjectedHandler.GetString();
}
}
how can I retrieve the correct handler as an interface by its attribute name? A large switch-case statement would be an obvious solution but I'm looking for a method similiar to the services.AddControllers() method which searches for the handlers by the attribute and registers all of them as transient services. My current search implementation for this is
IEnumerable<Type> handlerTypes = AppDomain
.CurrentDomain
.GetAssemblies()
.SelectMany(assembly => assembly
.GetTypes()
.Where(currentType => currentType.GetCustomAttribute<HandlerAttribute>() != null));
And inside the MyController.Get method, how can I retrieve the correct handler?