Premise
I never really wrestled with statements like or 'that's the way we do it because'. I've always been able to analytically think about why something is the way it is and either accept it because it has good reasons or write it off and refactor till it's "good". But as you will see, something in my heart is challenging my head.
Background
In a recent project, I found myself resolving collections of interfaces to carry out a bunch of common tasks. It is simple enough to do, but it's not intuitive, so let's see an example. Firstly, let's define an interface and a few concrete implementations:
services.AddSingleton<IWorkItem, ConcreteWorkItem1>();
services.AddSingleton<IWorkItem, ConcreteWorkItem2>();
services.AddSingleton<IWorkItem, ConcreteWorkItem3>();
Now when you resolve these wherever you need them, you can resolve them as:
public sealed class SomeClass(IEnumerable<IWorkItem> workItems)
And you will get all of the concrete implementations. Then you can go on to do the work, which will typically involve a foreach loop:
foreach(var workItem in workItems)
{
workItem.DoWork();
}
The 'Problem'
In this project, I have nearly 50 (and growing) of these "WorkItems" that all do business-valid things, essentially a bunch of independent and configurable calculations. I'm manually registering each one. Now this isn't really a problem. And I've always subscribed to Occam's razor, in which simply having 50 registrations is easy to understand for every level of engineer, so that's what I should do. That IS the correct answer. But I felt drawn to the "heart" solution, one that meant I didn't have to remember to register these each time one is created.
var assembly = Assembly.GetAssembly(typeof(IWorkItem));
var types = assembly.GetTypes()
.Where(t => t.IsClass
&& !t.IsAbstract
&& t.GetInterfaces().Contains(typeof(IWorkItem)));
foreach (var type in types)
{
services.AddSingleton(typeof(IWorkItem), type);
}
And that's that, each time one of the "WorkItems" is written, it's automatically injected without any thought towards it. It's by far more complicated to understand, definitely scary if you aren't comfortable with reflection, and will almost certainly produce a gut wrench in a code review. But do I unequivocally love the nature of it? Yes, I do. I can't pin down why, as this is not my normal nature, but it's here to stay.