3

I have the follow trouble, in my base controller i do dependency injection. And i have a class child with implementation of base controller and i need pass the constructor. So my doubt is, my way to implementation of dependency injection is correctly? If no, what is the best way to do this?

I use unity to implementate D.I, and my ide is VS2017 web api 2.

Follow this code i using: Base controller or parent controller:

public class BaseController : ApiController
{
    public string[] includes = null;

    private readonly IFiltroServico servico;
    public BaseController(IFiltroServico _servico)
    {
        servico = _servico;
    }
}

Base controller to generics types implements Base Controller:

 public abstract class BaseController<E, R, F> : BaseController
        where E : class
        where R : class
        where F : class
    {
    private readonly IFiltroServico servico;
            public AreaFormacaoController(IFiltroServico _servico): base(_servico)
            {
                servico = _servico;
            }
}

Child controller:

    public abstract class BaseController<R> : BaseController
            where R : class
        {
private readonly IFiltroServico servico;
        public AreaFormacaoController(IFiltroServico _servico): base(_servico)
        {
            servico = _servico;
        }
     //services of controller;
        }
  • There is no good way to use DI in a base controller, [nor is there a good reason to have one in the first place](https://stackoverflow.com/a/36224308). – NightOwl888 Mar 21 '18 at 15:29
  • @NightOwl888 I decided to do the DI, because my base controller is quite generic, ie regardless of the type it will work the methods will be defaults due to using a FilterService to reduce the direct dependency of the controller with the types that work. But still I did more to be able to learn to work with DI and know how to apply it correctly in the system. I have read your response even more so it was not clear enough how to apply the DI in this case. – Guilherme Caixeta Mar 22 '18 at 01:08

2 Answers2

3

You don't need to define the private field servico over and over again as it is already preset in the base controller. Just define it as protected readonly in the base class and use it in the childs.

Other than that your code is fine.

It is perfectly reasonable that a child has the same dependency parameters in the constructor as it inherits behavior of the base class that is most likely relying on the dependency.

Another option would be to use property injection in the base class but you need to add a unity specific attribute to the property. I don't like that as you bind your code directly to Unity.

ViRuSTriNiTy
  • 5,017
  • 2
  • 32
  • 58
1

Have you seen https://simpleinjector.org/index.html

check out git from https://github.com/simpleinjector/SimpleInjector

It is one of the best Inversion of Control library (IOC).

Only thing you need to do is register all your services and types.

using SimpleInjector;

static class Program
{
static readonly Container container;

static Program() {
    // 1. Create a new Simple Injector container
    container = new Container();

    // 2. Configure the container (register)
    container.Register<IOrderRepository, SqlOrderRepository>();
    container.Register<ILogger, FileLogger>(Lifestyle.Singleton);
    container.Register<CancelOrderHandler>();

    // 3. Verify your configuration
    container.Verify();
}

static void Main(string[] args)) {
    // 4. Use the container
    var handler = container.GetInstance<CancelOrderHandler>();

    var orderId = Guid.Parse(args[0]);
    var command = new CancelOrder { OrderId = orderId };

    handler.Handle(command);
}
}

Once you register all your types and services you can inject those services where ever you want

public class CancelOrderHandler {
private readonly IOrderRepository repository;
private readonly ILogger logger;
private readonly IEventPublisher publisher;

// Use constructor injection for the dependencies
public CancelOrderHandler(
    IOrderRepository repository, ILogger logger, IEventPublisher publisher) {
    this.repository = repository;
    this.logger = logger;
    this.publisher = publisher;
}

public void Handle(CancelOrder command) {
    this.logger.Log("Cancelling order " + command.OrderId);
    var order = this.repository.GetById(command.OrderId);
    order.Status = OrderStatus.Cancelled;
    this.repository.Save(order);
    this.publisher.Publish(new OrderCancelled(command.OrderId));
}
}

public class SqlOrderRepository : IOrderRepository {
private readonly ILogger logger;

// Use constructor injection for the dependencies
public SqlOrderRepository(ILogger logger) {
    this.logger = logger;
}

public Order GetById(Guid id) {
    this.logger.Log("Getting Order " + order.Id);
    // Retrieve from db.
}

public void Save(Order order) {
    this.logger.Log("Saving order " + order.Id);
    // Save to db.
}
}

Let me know if you have any queries, Thanks.

Venkat
  • 11
  • 3