First point - For simplicity, the answer by Rumen is correct.
What I do in larger solutions is to have a separate Infrastructure project which set's up the dependency injection container (in .net core, this would be the IServiceCollection).
For example in my current solution I have both a Website & an API.
Both of these call methods in my Infrastructure project to setup the dependency injection.
In my UI projects I can then decide which dependencies I want to setup without needing to know the code.
- For testing, I can use an extension method called "AddMockRepositories" e.g. "_serviceCollection.AddMockRepositories()"
- For Development, I can use "AddRepositories(connectionString)
- For Production, I can use "AddCachedRepositories(connectionString, objectCache)
There are 2 advantages to this approach:
- All of the DI code is in one project - We get to share this between other projects without duplicating any of the code. This includes being able to share the caching code which is extremely useful.
- The UI projects do not have to reference the DAL. This means no one can directly reference the DAL from the UI project, accidentally or not.
As a side note, I'm not sure how well this translates for other DI frameworks. I imagine they all set up dependencies similarly but I have only done the above using native .net core dependency injection.