liveBook · Manning

Dependency inversion

As explained in .NET MAUI in Action

Dependency inversion is a design principle in which higher-level code depends on abstractions rather than concrete implementation details.

Dependency inversion keeps higher-level code focused on what it needs instead of which class provides it. Define a small interface at the point of consumption, then supply an implementation separately. The consumer depends on required behavior, so implementations can change without changing the consumer. section 9.4 section 8.5

Start with a login requirement

A login page needs to log in; it does not need to know how authentication works. Define IAuthService in the UI project with LoginAsync returning Task<bool>. The button handler calls that interface, disables the button while work runs, displays activity feedback, and handles success or failure. A MockAuthService can initially satisfy the requirement while the real service is built. section 8.1.1 section 8.1.1 section 8.1.1

Figure 8.1 The LoginPage has a login button. This button triggers an event handler in the code-behind file. The event handler doesn’t handle the process of logging in itself; instead, it calls a Login method in an authentication service.

The login flow makes the boundary visible: the event handler delegates authentication to a service rather than performing it itself. section 8.1.1

Inject the interface rather than constructing a concrete service in the page. A constructor such as LoginPage(IAuthService authService) lets the service collection provide a fully resolved implementation, including that implementation’s own dependencies. This avoids coupling the page to a default constructor or a specific authentication class. section 8.2.2 section 8.2.2

Use dependency inversion in a practical sequence:

  • Identify the behavior a View or ViewModel needs, such as authentication, product lookup, or inventory updates. section 9.6
  • Declare a focused interface containing only that consumer’s needed operations; split larger implementations across interfaces when consumers need different operations. section 9.4
  • Build an implementation afterward and register dependencies with the host builder’s service collection. section 9.6 section 9.7
  • Receive dependencies through constructors; do not resolve them globally through a service locator. section 8.2.2
  • Keep UI, presentation, and business responsibilities separate so an implementation can change behind its interface. section 9.6

The value is loose coupling and easier maintenance. UI appearance can change without rebuilding services, and a REST API can be replaced with GraphQL by changing service implementations while interfaces and other app parts remain intact. MVVM supports this structure by separating View, ViewModel, and Model responsibilities. section 9.6 section 9.7

How .NET MAUI in Action covers it

How deep it goes
Explains consumer-defined, focused interfaces and constructor injection, while deferring deeper SOLID treatment.
Examples
Uses login authentication, a Sum dependency, inventory services, and swapping a REST API for GraphQL.
What it assumes
Assumes some familiarity with interfaces and SOLID concepts, but demonstrates the principle through simple consumer requirements.
What you can do after
Apply it via constructor injection and ServiceCollection to replace service implementations without changing consumers.
How it connects
Connects dependency inversion to MVVM, dependency injection, ServiceCollection, service locator, and separation of concerns.

Also explained in

Compare how 6 books explain dependency inversion →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of .NET MAUI in Action. The section links point to the parts of the book it draws on.