I am building a 3 tier architecture with a Presentation Layer (PL), Business Logic Layer (BLL) and a Data Access Layer (DAL).
Conventional 3 tier architecture logic states that BLL should act as a mediator between the PL and the DAL. The PL shouldn't be even aware that there is a Database while the DAL should not be aware that there is a BLL or a PL.
Implementing above would create following dependencies among the 3 different physical projects as follows
- PL Project -> Reference of BLL DLL
- BLL Project -> Reference of DAL DLL
- DAL Project -> No Reference
However applying the concept of IOC between the BLL and the DAL by defining interfaces in the BLL for the DAL to implement and using DI via constructor injection will change the dependency as follows
- PL Project -> Reference of BLL DLL, Reference of DAL DLL (for DI of concrete types to constructors of the BLL Objects)
- BLL Project -> No Reference
- DAL Project -> Reference of BLL DLL (for implementation of BLL Interfaces)
So are IOC and traditional 3 tier in conflict ?
Ideally I want to achieve the following, while maintaining my IOC with DI.
- PL Project -> Reference of BLL DLL
- BLL Project -> No Reference
- DAL Project -> Reference of BLL DLL
How do you do this ?
First up, you can consider decoupling your layers using interfaces, and the interfaces can be separated into separates dll's. This way, each layer only has a dependency on the interface of the layer below.
I'm also not sure why you would need coupling from DAL to BLL? Is this for call backs? Can't you use events instead?
Assuming all 3 tiers run in process, and assuming your PL is the 'entry point' to your app (Composition Root), IMO the usual dependency if you've separated out interfaces, with the bootstrap code in the PL, is:
- PL => References to BLL and DAL (concrete and interfaces), and the IoC container
- BLL References DAL (or just the Interface, if applicable)
- DAL no Dependency (although usually will have a dependency on DTO / POCO / Entities)
The PL can offload the IoC configuration to a Bootstrapper dll, resulting in:
- PL => References to BLL Interface and bootstrapper
- Bootstrapper => References everything and the IoC container
- BLL => References DAL Interface
- DAL => No Dependency (although usually will have a dependency on DTO / POCO / Entities)
With some containers, you can avoid the requirement to reference all the dll's from the bootstrapper by using configuration, or convention. However, these dlls obviously still need to be deployed with your app.