Confusion in the blog post
How is the Infrastructure layer supposed to get to these interfaces? From the looks of his Onion Architecture model, the flow of references look like this:
Infrastructure -> Application Services -> Domain Services
You are correct that there seems to be some confusion on the specific layers being used in the blog post itself.
The first layer around the Domain Model is typically where we would find interfaces that provide object saving and retrieving behavior, called repository interfaces. The object saving behavior is not in the application core, however, because it typically involves a database. Only the interface is in the application core. Out on the edges we see UI, Infrastructure, and Tests.
These two statements imply that "the first layer around the Domain Model" is "the application core", but on the graph they are different. "The first layer around the Domain Model" is Domain Services, and "the application core" is Application Services. That's either a contradiction or a mistake in the explanation.
If you ignore the image and only read the explanation, the blog post seems to lump the Application Services and Domain Services (from the circular graph image) together as "the application core".
The added graph just doesn't quite match, this may have been a simple oversight when adding the reference image.
Note that this is how I also structure my layers in my solutions, where the Application Services and Domain Services from the image are just one "Application" layer. I agree with that approach as described by the explanation, but the added graph just doesn't quite match.
For the purpose of this answer, I'm going to follow the explanation, not the image; and lump the "application services" and "domain services" layers from the image together and call them the "Application" layer.
A more correct representation would be
Test -> Application <- Infrastructure
Note: we can argue about the direction of the arrow. In the above case,
A -> B means that A has a project dependency on B. I usually flip those arrows around because it matches my mental picture of a dependency graph.
Note that this flow mirrors the general intention of the picture with the circles you posted: the application layer sits in the middle (wrapped around the domain), and the other layers surround it.
Or using my favorite resource on the topic (all credit goes to Jason Taylor):
Note that this graph separates Persistence from Infrastructure, but that's an irrelevant distinction for the current question. You can lump these together if it makes more sense to you.
In the Clean Architecture solution template that Jason Taylor authored (much more recently than these slides), Persistence has also been lumped back into the Infrastructure layer
Using inverted dependencies
First, realize that when your applications runs, all layers are available at the same time. This is essential to understanding why dependencies can be inverted.
During compile time, your Application layer doesn't need to know exactly who implements your
IRepository interface. It only needs to know that the
IRepository interface itself exists. It blindly trusts that (at runtime) it will receive a valid implementation of that interface.
During runtime, the top-level application registers your concrete
Repository class (in the Infrastructure layer) as that
IRepository interface (from your Application layer). Something along the lines of:
Note: whether the top-level application registers this itself, or delegates that responsibility back to the Infrastructure layer, is not relevant right now. I generally prefer the latter but the principle remains the same.
Your top-level application can do that because it inherently has access to all of the libraries that it uses, in this case your Application and Infrastructure projects.
This is what's called an "inverted" dependency.
A normal dependency would be one where if
B as a dependency, then
A's project would have a project dependency on
B's project. In this example, that would mean that
Application depends on
Infrastructure would be providing both the
IRepository interface and the
Repository : IRepository class.
But in an inverted dependency, if
B as a dependency, then
B's project has a project dependency on
A's project. That's the other way around, which is why it's called an inverted dependency. To make this possible, it requires
A's project to define the interface and
B's project to implement the interface.
In your case, that means that
Infrastructure depends on
Application provides (and works with) an
IRepository interface, and
Infrastructure will implement a concrete
Repository : IRepository.