Injecting Services
Once a service is registered, it can be injected into components that Mach constructs.
Mach uses constructor injection: a component declares its dependencies as constructor parameters, and those dependencies are listed when the component is registered.
Inject Services into Controllers
Section titled “Inject Services into Controllers”Controllers can receive registered services through their constructors.
For example:
class UserService {public: std::string getName() const { return "Alice"; }};A controller can depend on UserService:
class UsersController final : public mach::ControllerBase {
public: inline static constexpr std::string_view route = "/users";
explicit UsersController(UserService& userService) : m_userService(userService) {}
mach::Reply<std::string> index() { return ok(m_userService.getName()); }
static void configure(mach::ControllerBuilder<UsersController>& builder) { builder.mapGet("/", &UsersController::index); }
private: UserService& m_userService;};Register the service and declare it as a controller dependency:
mach::AppBuilder builder;
builder.addScoped<UserService>();builder.addController<UsersController, UserService>();
auto app = builder.build();Mach resolves UserService and passes it to the controller constructor.
Inject Services into Middleware
Section titled “Inject Services into Middleware”Middleware uses the same constructor injection model.
class LoggingMiddleware {
public: explicit LoggingMiddleware(mach::Logger& logger) : m_logger(logger) {}
void invoke(mach::Context& context, mach::Next& next) { m_logger.info("Request received");
next(); }
private: mach::Logger& m_logger;};Declare the dependency when registering the middleware:
mach::AppBuilder builder;
builder.use<LoggingMiddleware, mach::Logger>();
auto app = builder.build();Mach supplies the dependency when it constructs the middleware.
Inject Multiple Services
Section titled “Inject Multiple Services”A component can receive more than one dependency:
class UsersController final : public mach::ControllerBase {
public: UsersController(UserService& userService, AuditService& auditService) : m_userService(userService), m_auditService(auditService) {}
// ...
private: UserService& m_userService; AuditService& m_auditService;};List the dependencies in the same order when registering the component:
builder.addController<UsersController, UserService, AuditService>();Injection and Lifetimes
Section titled “Injection and Lifetimes”Injection does not change a service’s lifetime.
When Mach resolves a dependency, the service’s registered lifetime determines which instance is provided:
- A scoped dependency is reused within its request scope.
- A singleton dependency is shared across the application.
- A transient dependency is newly created when resolved.
This means components can depend on services with different lifetimes, provided the lifetime relationship is valid.
You’ve now covered Mach’s dependency injection system: registering services, choosing lifetimes, defining dependencies, and injecting services into application components.