title: 'Module reference · Nael Framework' description: 'Use ModuleRef to resolve providers dynamically, create scoped instances, and interact with module-scoped injectors.'

Fundamentals

Module reference

ModuleRef exposes the underlying injector so you can look up providers outside of constructor injection. Use it sparingly for dynamic workflows, plug-in systems, or bridging circular dependencies.

Resolving providers at runtime

Call moduleRef.resolve(Token) to retrieve a provider using the same injection graph Nael builds at bootstrap. The promise resolves once the provider is ready; if it was request-scoped, it will honor the current context.

Inject ModuleRef
import { Injectable } from '@nl-framework/core';import { ModuleRef } from '@nl-framework/core';@Injectable()export class ReportsService {  constructor(private readonly moduleRef: ModuleRef) {}  async sendWeeklyReport() {    const email = await this.moduleRef.resolve(EmailService);    await email.send('ops@example.com', 'Weekly status', '...');  }}

Controlling lookup boundaries

By default, resolve() searches the entire module graph. Pass strict: true to restrict the lookup to the current module (and its providers). This is useful for enforcing encapsulation.

Strict resolution
const cache = await this.moduleRef.resolve(CacheService, {  strict: true,});// Throws if CacheService is not part of the current module tree.

Creating new instances

Use moduleRef.create() when you need a throwaway instance that should not be cached by the container. Nael will construct the provider and resolve its dependencies, but ownership stays with the caller.

Per-call instances
const exporter = await this.moduleRef.create(ExporterService);await exporter.export();// create() bypasses the shared singleton and gives you a fresh instance.

Accessing module-scoped providers

When you need to traverse module boundaries manually, moduleRef.get() accepts strings, class tokens, or symbols. Combine it with strict: false to reach exported providers from imported modules.

Look up by module token
const billingModule = this.moduleRef.get('BillingModule', { strict: false });const billingService = billingModule.get(BillingService);

Prefer constructor injection or explicit exports whenever possible; ModuleRef is a powerful escape hatch but can reduce clarity if overused.