C# Dependency Injection – Manual Dependency Injection Examples Still Tightly Coupled

cdependency-injectioninterfacesinversion-of-control

I've been using AutoFac for some time now to take care of the dependency injection we're using in a web project. All is well, but I now want to demonstrate DI outside of an AutoFac context for reasons irrelevant to this question.

In doing so, I'm having to read up on 'manual' methods of achieving this pattern. All of the examples in tutorials work (obviously), but the issue of tightly coupled objects still exist.

Take this for example: http://www.devx.com/dotnet/Article/34066/0/page/2

The constructor of the dependent class takes an interface:

public class BusinessFacade {
    private IBusinessLogic businessLogic;
    public BusinessFacade(IBusinessLogic businessLogic) {
        this.businessLogic = businessLogic;
    }
}

But then the instantiation of BusinessFacade still requires a concrete implementation to be passed, which means an implementation needs to be instantiated:

IBusinessLogic productBL = new ProductBL();
BusinessFacade businessFacade = new BusinessFacade(productBL);

Question

Now I know, somewhere at some point, something (whether it is a container or manually written code) will have to decide on the implementation to choose, but how can I come to terms with the benefit of moving such decision outside of the dependent class? Of course the BusinessFacade class is no longer tightly coupled, but we're still very explicit about which implementation we choose – so what's been gained here? Is it purely for the fact we can mock out the dependencies?

Best Answer

The fact that a BusinessFacade object can take any such implementation of IBusinessLogic is such that you are decoupled so long as you follow SOLID principles of design in your objects.

The typical idea that you brought up that ProductBL property can now be mocked in a unit test is one particular benefit that you mentioned. The other is that if you have requirements in the future for additional IBusinessLogic implementations then you can simply use the same BusinessFacade class and create many container managed objects of type BusinessFacade that could be wrapping many various implementations. You probably will organize them and name them properly in your DI configuration.

It may seem pointless, but probably only because of what it is I think you are doing.

All is well, but I now want to demonstrate DI outside of an AutoFac context for reasons irrelevant to this question.

If you are newing up objects outside of your container like in your code example then how is that Dependency Injection? If AutoFac doesn't monopolize DI in your project then how can any of your code have any reasonable assurance as to unstated and unconfigured dependencies that could exist in an object? This is really beyond the scope of your question but I thought it was worth mentioning that you might not be seeing the benefits of DI simply because it sounds to me from an outsiders perspective that you are purposely trying to circumvent it and work against it.

Now I know, somewhere at some point, something (whether it is a container or manually written code) will have to decide on the implementation to choose,

The container should always choose or what is the point of using DI at all.