This question already has an answer here:
I am trying to learn about DI, to have a better understanding of IoC, and the other benefits.
Pre DI, I have a project that has a UI project (MVC), a BusinessLogic project and a DataAccess project. I also have a SharedLib project. All projects have a reference to SharedLib. UI has a reference to BusinessLogic, and BusinessLogic has a reference to DataAccess.
I want to add the Interfaces now. So I go to my DataAccess, and add an Interface for each class, and populat them with their methods. I do the same for the business logic layer.
But in order to inject the DataAccess class, which I instantiate in the BusinessLogic class in the UI project, I need a reference to my Data project, because the UI project (correctly, I think) has no idea what an 'IDataAccess' interface is. The only fix I can see is to add a project reference in my UI to my DA project - which seems wrong.
And if I try add Unity as my container (One day in the future, once i work out how that all works), and want to initialise my Interface/Class relationships in the UI project - same issue.
Maybe the interfaces must go in some shared project? Or one project up? How should this be handled?
If you don't want the references between projects you could look into factories/abstract factories.
Your UI knows about your business layer, so you want to define a factory in your business layer which knows how to use the data layer. Then you handle all your DI in your composition root (the UI project in this example).
A simple example below using a console app as the UI, sticking to the references you stated in your question
Data layer
Business layer
UI
It's a contrived example so it looks like abstraction for nothing, but with a real world example it would make more sense.
e.g. you might have a bunch of different data access classes in your data layer database, xml files, etc. so you might define a factory for each in your business layer.
Using abstract factories
The factory could contain a lot more logic about the nitty gritty of the data layer, or as an abstract factory provide a set of individual factories to the business logic layer.
Business layer
You might instead have an abstract factory in the business layer such as
with a concrete factory
(You might have additional concrete factories such as
RetailPlatformFactory
, etc.)Your
BusinessLogic
class would now look something likeData layer
Your business layer no longer needs to provide an
IDataAccessFactory
to your UI so you can move it into your data layer in this example. So the data layer classes would beUI
Now you'd in the UI you'd configure the container and perform similar actions as
The UI then knows nothing about the data layer/access, it's just handing off the factory creation to the business layer, which holds the data (and pricing) references.
Some recommended reading:
Composition Root
Implementing an Abstract Factory
Compose object graphs with confidence