Reputation: 1079
I try to design my applications always in a modular fashion. I want to be able at any given to swap modules.
Using the dependency injection pattern allows me to do just that. But there is something that keeps bothering me a lot.
In most of the code I come across there is a single place where interfaces are linked to the desired interface. For example in asp.net vnext it looks something like this:
public void ConfigureServices(IServiceCollection services)
{
// business-layer
services.AddTransient<IArticleRepository, ArticleRepository>();
// data-layer
services.AddTransient<IDataConnection, DataConnection>();
}
But I don't like that there is only one place to do the registration. I would rather have each module register their own interfaces/implementations:
In my business layer (module)
public void ConfigureServices(IServiceCollection services)
{
// business-layer
services.AddTransient<IArticleRepository, ArticleRepository>();
}
In my data layer (module)
public void ConfigureServices(IServiceCollection services)
{
// data-layer
services.AddTransient<IDataConnection, DataConnection>();
}
Is there any pattern, or best-practice to do this kind of things? I could create some interface and on load go through all the implementations of this interface, but I'm not sure if this is the best way to do this.
Upvotes: 4
Views: 484
Reputation: 14550
i would say that way/place of configuring your DI depends highly on your DI framework. some frameworks let you do per-module configuration others require one global configuration. in the latter case you can manually delegate to your submodules (just pass the IServiceCollection
to submodule configuration code).
regarding best practices: i rarely see usage of DI to have multiple production implementations. usually there is just one production implementation and DI is used just to wire together everything without the boilerplate. but many different implementations (usually mocks) are used in testing usually with manual wiring without the DI framework. if that's also your case then your gut-felling is right: it would be nice to have DI framework that scan the whole code, take the default/only implementation and inject it as a dependency. if your DI framework provides that functionality you're lucky. if not, you have to implement it by yourself
Upvotes: 0
Reputation: 233160
Is there any pattern, or best-practice to do this kind of things?
Yes and no. There's the Facade pattern where you provide a simplified API to clients that don't need fine-grained control of your API. The Facade pattern doesn't explicitly concern itself with Dependency Injection, but you can always provide a default composition of services if that's a meaningful thing to do. There are more details in my article DI Friendly Library.
That said, it's important to keep the API open, so that the Facade is only one of the options you provide to clients. If you pre-compose an object graph within a library, and don't provide clients any way to circumvent that default composition, such a library would be a monolithic black box. All external benefits from Dependency Injection would be gone, because a client wouldn't be able to replace or extend services.
Do follow the guidelines outlined in the DI Friendly Library article, but be sure to avoid the Conforming Container anti-pattern.
Upvotes: 2