Achilles
Achilles

Reputation: 1129

How to create a base class that accepts parameters for controllers without changing child controllers?

I'm trying to add ninject to the following setup -

public class BaseController : Controller
{
    protected ILogger Logger {get;}
    public BaseController() { Logger = new MyLogger(); }
}
public class Controller1Controller : BaseController { ... }
public class Controller2Controller : BaseController { ... }
....
public class ControllerNController : BaseController { ... }

With ninject, adding an ILogger parameter to BaseController works great -

public class BaseController : Controller
{
    protected ILogger Logger {get;}
    public BaseController(ILogger logger) { Logger = logger; }
}

but now it also requires adding a constructor in each of the child controllers because the base class no longer has a parameterless constructor-

public class Controller1Controller : BaseController { 
    public Controller1Controller(ILogger logger) : base(logger) { }
}

There are over 50 child controllers and going forward it might become a bit of a maintenance problem if we have to add/remove more dependencies. Further, the code being added to each controller is exactly the same.

Is there a way to keep the child controllers as they are (without any constructors) but still make that change to the BaseController?

Upvotes: 2

Views: 790

Answers (3)

tomludd
tomludd

Reputation: 96

Sorry but no.

As an alternative solution you can get ILogger from Ninject: Using property injection instead of constructor injection

Upvotes: 1

Numan
Numan

Reputation: 3948

Simple answer: No (You have to update your derived class constructors)

Explanation: For injected instance of ILogger to be passed across derived and base classes, you need to update your derived constructors with ILogger parameter and then forward the parameter to the base. Unless, there is a wiser solution to this situation.

See the first point in disadvantages section on wiki DI Disadvantages (DI comes with this baggage)

Additionally: You can create a protected member in the base class to hold the ILogger instance, which will make this protected instance accessible to all the derived classes.

Update: Partially agree with tomludd's solution of using Property injection. See this SO answer. For more DI techniques, please do read articles/blogs from Mark Seemann or his book DI in .NET

Upvotes: 1

kgzdev
kgzdev

Reputation: 2885

Try this in BaseController constructor

public BaseController(ILogger logger = null) 
{ 
    if (logger != null)
        Logger = logger;
    else
        Logger = new MyLogger();
}

Upvotes: 0

Related Questions