Reputation: 39190
I have a controller looking like this.
public SomeController : Controller
{
private readonly InjectableIntoEveryController _thing;
public SomeController(InjectableIntoEveryController thing, ...) { ... }
}
Naturally, the dev in me wants to move the thing that is InjectableIntoEveryController to a base controller and avoid the explicit and omittable injection. So I'm creating the following.
public BaseController : Controller
{
private readonly InjectableIntoEveryController _thing;
public BaseController(InjectableIntoEveryController thing, ...) { ... }
}
public SomeController : BaseController
{
public SomeController(...) { ... }
}
This doesn't compile because there's no parameterless constructor in the base class. However, if we add one as show below, no injection takes place, which fails the aim.
public BaseController : Controller
{
private readonly InjectableIntoEveryController _thing;
public BaseController() { ... }
public BaseController(InjectableIntoEveryController thing, ...) { ... }
}
The only way to make it fly I've found was to pass the thing using base(...) call but that requires it to be injected, which defeats the purpose of the whole refactoring.
public SomeController : BaseController
{
public SomeController(InjectableIntoEveryController thing, ...)
:base(thing) { ... }
}
Is there a better way to ensure that the base controller gets injected stuff as I'd like them to without explicitly passing them from the inheriting one?
Upvotes: 2
Views: 1860
Reputation: 168
I ran in the same problem today and read this question. The accepted solution didn´t satisfy my needs, because there is no BaseController doing the injection. Here is a solution that allows you to inject directly into the BaseController class avoiding constructor injection and all its disadvantages with inheritance:
public class BaseController : Controller
{
private InjectableIntoEveryController _thing;
public InjectableIntoEveryController Thing
{
get
{
if (_thing == null && HttpContext != null)
_thing = (InjectableIntoEveryController)HttpContext.RequestServices.GetService(typeof(InjectableIntoEveryController));
return _thing;
}
}
}
Upvotes: 2
Reputation: 980
One simple way to achieve your goal of not having to specify each dependency every single time is to dump your dependencies into a container class and then inject that into all of your controllers:
public class Dependencies : IDependencies
{
public Dependencies(IDependency1 d1, IDependency2 d2, <etc>)
{
this.d1 = d1;
this.d2 = d2;
<etc>...
}
}
In your controllers, you can now simply inject that class.
public SomeController
{
public SomeController(IDependencies d) {
this.d = d;
}
}
Its signature will never change even if you have to add/remove dependencies, so all of your controllers can access their shared dependencies without having to modify their signatures every time your dependencies change.
I will concur with the comments, though: if this is a solution to a problem you have, then you might want to examine why one class has so many dependencies (or why so many classes all have an identical list of them). I can definitely understand being constrained by circumstance, though (which is to say, I've used this solution myself)!
Upvotes: 3