Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to passing IOC container around

I had the following base class with several dependencies:

public abstract class ViewModel
{
    private readonly ILoggingService loggingService;

    public ViewModel(
        ILoggingService loggingService,
        ...)
    {
        this.loggingService = loggingService;
        ...
    }
}

In my derived class, I don't want to have to repeat all of the parameters in this base class constructor, so I did this:

public abstract class ViewModel
{
    private readonly IUnityContainer container;
    private ILoggingService loggingService;
    ...

    public ViewModel(IUnityContainer container)
    {
        this.container = container;
    }

    public ILoggingService LoggingService
    {
        get
        {
            if (this.loggingService == null)
            {
                this.loggingService = this.container.Resolve<IUnityContainer>();
            }

            return this.loggingService;
        }
    }

    ...
}

Now my derived classes only need to pass one thing to my base class constructor. I also have the nice effect of having my dependencies resolved only when they are needed.

However, I have since learned it is a bad idea to pass an IOC container around. What's the best alternative design pattern, bearing in mind that many of the services passed in have been registered with my IOC container as a singleton?

like image 717
Muhammad Rehan Saeed Avatar asked Dec 01 '22 04:12

Muhammad Rehan Saeed


2 Answers

As you state, you should avoid passing the container around. This turns it into a "bag of holding", where you can no longer see what your dependencies are, and you can't easily see what's in the bag.

Instead, if you find that your constructor takes far too many parameters, this is a smell by itself. In this case, you'll often find that your class is trying to do too many things (it's violating the single responsibility principle).

Take a look at your parameter list, and see if you can group the parameters into smaller groups. For example, if your constructor takes IEmailSender, IEventLog and ILoggingService, maybe what you really need is an INotificationService which aggregates these three dependencies.

Of course, sometimes you do have a constructor with that many dependencies. In this case, the class is probably just used to gather these things together and to wire them up. If this is the case, the class should probably avoid doing any actual work.

like image 97
Roger Lipscombe Avatar answered Dec 05 '22 04:12

Roger Lipscombe


Passing all dependencies in the Constructor is the cleanest way.

I do not see the problem in passing parameters in derived classes. Avoid typing is the wrong motivation and there are tools like Resharper helping you to generate these constructors.

If you have a lot of dependencies it indicates, that the class violate Single Responsibility Pattern.

In many cases its also a good think to favor Composition over Inheritance. This also helps to split classes into smaller pieces which do not violate SRP.

like image 44
Sven Neubert Avatar answered Dec 05 '22 03:12

Sven Neubert