0

I have a controller's constructor in which I want to instantiate an object that gets access to the repository via dependency injection.

like this:

ContactController.cs: I get an error because I don't pass an IContactRepository

private ContactOperationsFacade contactOperator;

ContactController(){
    contactOperator = new ContactOperationsFacade(//I want to use DI here);
}

ContactOperationsFacade.cs:

private readonly IContactRepository contactRepository;

public ContactOperationsFacade(IContactRepository contactRepositor){
    this.contactRepository = contactRepository;
}

How can I instantiate this ContactOperationsFacade object in the controller's constructor still using DI for the repository?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
Matias Miraglio
  • 513
  • 1
  • 4
  • 19
  • 2
    Just inject `IContactRepository` into the controller and use it when you new up the facade. – JSteward Sep 11 '18 at 20:49
  • is that the only way? I don't wanna have a dependency on the IContactRepository in my controller if possible – Matias Miraglio Sep 11 '18 at 20:55
  • 2
    then register `ContactOperationsFacade` with IoC container and inject it instead, or use service locator but it's an anti-pattern: https://stackoverflow.com/questions/32459670/resolving-instances-with-asp-net-core-di and basically what @JSteward says below – Konrad Sep 11 '18 at 21:02
  • 2
    Well you could inject whatever DI container you're using. But why can't you inject the `ContactOperationsFacade` instead of newing it up? – JSteward Sep 11 '18 at 21:02
  • 1
    You *already* have a dependency on it. If it's necessary for your controller to do what it needs to do, then its a dependency. Newing it up inside the controller itself, simply hides the fact that the dependency is there, whereas making it required in the constructor properly advertises the dependency. If you want to use DI (and you should), you need to use DI *all the way*. – Chris Pratt Sep 12 '18 at 13:10
  • 2
    Sorry. I actually misread the comment. You do not need the controller to have a dependency on `IContactRespository`, but it does have a dependency on `ContactOperationsFascade`. Therefore, it should be injected into you constructor, rather than newing it up in the constructor. – Chris Pratt Sep 12 '18 at 13:13
  • I have many similar classes like ContactOperationsFacade and I don't wanna just inject all of them. I'm trying to have code that's easy to unit test (by making my methods not have any external dependencies, only primitive types) without abusing DI – Matias Miraglio Sep 13 '18 at 18:05
  • @ChrisPratt should all the dependencies of controllers be injected? – Matias Miraglio Sep 13 '18 at 18:15
  • 2
    *All* dependencies should be injected. So, yes, dependencies for controllers apply as well. – Chris Pratt Sep 13 '18 at 18:19
  • @ChrisPratt so you never new up objects in your code? always using DI? – Matias Miraglio Sep 13 '18 at 18:30
  • 1
    Yep. I mean it doesn't mean you never use the `new` keyword again. There's plenty of things you'll new up, but mostly things like entity classes, view models, etc - things that are inherently transient in nature, don't have dependencies of their own, etc. – Chris Pratt Sep 13 '18 at 19:09

2 Answers2

2

In asp.net core you can do DI chaining as long as scopes allow it. So if A depends on B and the controller wants A you just add both A and B to the di container (ConfigureServices part of your code) and the container will figure it out.

Read more here https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1

stephanV
  • 183
  • 6
1

ContactController should follow The Explicit Dependencies Principle

Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.

Also classes should depend on abstractions and not coupled to concretions.

So assuming something like

public class ContactOperationsFacade: IContactOperationsFacade { //<-Note interface/contract

    private readonly IContactRepository contactRepository;

    public ContactOperationsFacade(IContactRepository contactRepositor){
        this.contactRepository = contactRepository;
    }

    //...
}

The controller should depend on the abstraction that the facade is derived from

public class ContactController: Controller {

    private readonly IContactOperationsFacade contactOperator;

    public ContactController(IContactOperationsFacade contactOperator){
        this.contactOperator = contactOperator;
    }

    //...

}

And assumes that all the interfaces and implementations are registered with the DI container.

services.AddScoped<IContactOperationsFacade, ContactOperationsFacade>();

once all dependencies are registered the service provider should resolve them when activating the controller.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • I can inject a IContactRepository into my controller without any trouble, so. Why can't I inject a IContactRepository into my IContactOperationsFacade just as easly? I have many similar classes like ContactOperationsFacade and I don't wanna just inject all of them. I'm trying to have code that's easy to unit test (by making my methods not have any external dependencies, only primitive types) without abusing DI @Nkosi – Matias Miraglio Sep 14 '18 at 18:50