With StructureMap, can one inject instances based on their name by convention, like so:
Ctor:
public HomeController(IQuery getItemByProductNumberQuery, IQuery getCustomerById)
StructureMap config:
x.For<IQuery>().Add<GetItemByProductNumberQuery>().Named("getItemByProductNumberQuery");
x.For<IQuery>().Add<GetCustomerById>().Named("getCustomerById");
I’m working with legacy code, so changing the DI container is a huge undertaking, but it would be interesting to know about other containers’ solution to the problem at hand as well.
It seems to me that you are missing an abstraction in your code base. Under normal circumstances, a service (
IQueryin your case) should be unambiguous, which isn’t the case in your situation. Identifying them by the argument name is often error prone and leads to a DI configuration that is hard to maintain. This doesn’t always have to be this way (as can be seen in this example), but it probably is in your case.To solve this, make your
IQueryinterface generic:This allows you to register all implementations of this interface by their closed generic representation, and allow your control to depend on this closed generic representation:
As you can see, each query defines a ‘XXXParameters’ object. This is a DTO that contains all parameters needed to run the query. The code in your
HomeControllermight look like this:It might be a bit difficult to batch register all
IQuery<TParameter, TResult>implementations in one go with StructureMap, but this SO question might help. And if not, using another DI container might yield better results.You can find more information about why you want to model your queries this way in this article: Meanwhile… on the query side of my architecture.