13

I am learning about the Onion Architecture. I have a confusion about the service layer, because I see some people saying that the core layer should only contain:

  • Models
  • Repository interfaces
  • Services interfaces

But others express that it also should implement the services interfaces. So what layer should implement the services interfaces?

I thought that the infrastructure layer should implement:

  • Repository Interfaces
  • Services Interfaces

And inject them to UI layer and Test layer when requested.

Thank you!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
reliasr
  • 175
  • 1
  • 8
  • 3
    According to Jeffrey Palermo: *"The overall philosophy of the Onion Architecture is to keep your business logic and model in the middle (Core) of your application and push your dependencies as far outward as possible. The problem domain is then completely independent of the required infrastructure (testing, databases, security, etc.). For example, this means that testing database accesses can be done thoroughly without a real database."* – Robert Harvey May 31 '13 at 15:47
  • That means that if a class WorkOrderService that implements a service interface IWorkOrderService, need a repository IOrderRepository then it would need a class OrderRepository that implements that repository interface and by design that class is outside(Infraestructure layer), so the service class WorkOrderService can not use it. Do you see the problem? In the other way: if you implement the service interface IWorkOrderService outside the core,you can use DI/IoC for getting repository IOrderRepository instances and get the job done. There is my consufion. – reliasr May 31 '13 at 16:31
  • 2
    You should include that in your question. – Robert Harvey May 31 '13 at 16:33

2 Answers2

28

The core layer should contain:

  • Models/Entities/POCOs/Whatever_the_name... it's all about domain objects
  • ALL the interfaces (including repositories and services)
  • Your core business services implementation (*)

(*) If your business is about handling orders, then the implementation of your IWorkOrderService should be in the core layer. If your WorkOrderService needs to access let's say a ShippingService (which is not your business), then it will only manipulate the IShippingService defined in the core layer and the IShippingService implementation will be somewhere in the infrastructure layer.

If your WorkOrderService needs an OrderRepository it will be done excatly the same way.

Here's a code example:

namespace MyBusiness.Core.Services
{
  internal class WorkOrderService: IWorkOrderService
  {
    public WorkOrderService(IOrderRepository orderRepository, IShippingService shippingService)
    {
      _orderRepository = orderRepository;
      _shippingService = shippingService;
    }

    ...
  }
}

This will be up to the outermost layer of your onion architecture - the Dependency Resolution Layer - to bound all your interfaces with the right service implementation at run time.

For<IWorkOrderService>().Use<Core.Services.WorkOrderService>();
For<IShippingService>().Use<Infrastructure.Services.ShippingService>();
For<IOrderRepository>().Use<Infrastructure.Data.OrderRepository>();
MaxSC
  • 4,698
  • 2
  • 23
  • 36
  • Say you're setting up a DbContext interface in core. this means you need to add EF as a dependency of the core project. Is this acceptable? If not, where does this interface go? – Douglas Gaskell Oct 22 '18 at 05:48
  • Hhello @DouglasGaskell. The `Core` project must not reference any kind of external libraries/framework. Therefore `DBContext` should be moved to the `Infrastructure` layer. I sort of have an example [here](https://stackoverflow.com/questions/16945104/onion-architecture-entity-framework-code-first-models-dataannotations/16961124#16961124) – MaxSC Oct 25 '18 at 09:33
  • Hi Max, to be clear, the `IDbContext` interface living in the Infrastructure layer is acceptable? And it's fine to reference the Infrastructure layer in tests for it? I'm wondering if that will cause confusion as all other interfaces have been able to be in `Core` thus far. – Douglas Gaskell Oct 26 '18 at 22:08
0

Service is the a core business logic of your application, entire working flow and you can't provide the implementation from outside(from infrastructure layer). Only repositories should be implemented from the outside, because they are specific, for example you implemented DB connections with Ado.net, but one day you decided to change it with EF.core. You should create new class in infrastructure and implement the same repository interface from core. Erom executable project You can control which implementation to use.