inject_x 0.0.6 copy "inject_x: ^0.0.6" to clipboard
inject_x: ^0.0.6 copied to clipboard

A minimalistic Dependency Injestion solution similar to the Angular one

InjectX #

CI

A lightweight, easy-to-use service locator implementation for Dart applications. This package provides a simple dependency injection container that helps manage application dependencies with minimal setup.

Features #

  • Simple registration and retrieval of dependencies
  • Singleton instance management
  • Automatic disposal of services
  • Type-safe dependency injection
  • Angular-style inject function
  • Lazy and async factory registration
  • Circular dependency detection
  • Zero external dependencies

Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  inject_x: ^0.0.6

Usage #

Basic Usage #

// Register your dependencies
InjectX.add<UserService>(UserService());
InjectX.add<AuthService>(AuthService());

// Retrieve instances
final userService = InjectX.get<UserService>();
final authService = InjectX.get<AuthService>();

// Alternatively, use Angular-style injection
final userService = inject<UserService>();

Init Method #

If your class defines an init() method, it will be called automatically before the first injection. This is useful when your service depends on other services that need to be resolved after construction — particularly in cases of circular dependencies.

class UserService {
  late AuthService authService;

  void init() {
    authService = inject<AuthService>();
  }
}

The init() method is called only once, just before the first access via get() or inject(). If init() throws, the error propagates to the caller and subsequent calls will retry init().

Async Init Method #

If your class has an async init() method (returning a Future), you can use injectAsync<T>() or InjectX.getAsync<T>() to ensure initialization is awaited before use.

class ConfigService {
  String? config;

  Future<void> init() async {
    await Future.delayed(Duration(milliseconds: 100));
    config = 'loaded';
  }
}

void main() async {
  InjectX.add(ConfigService());
  final config = await injectAsync<ConfigService>();
}

Automatic Disposal #

InjectX automatically calls a service's dispose() method if it exists when the service is removed:

class DatabaseService {
  void dispose() {
    // Cleanup resources
  }
}

// Register the service
InjectX.add<DatabaseService>(DatabaseService());

// Later, remove it
InjectX.remove<DatabaseService>(); // dispose() will be called automatically

Lazy Registration #

Create the instance only when it's first requested:

InjectX.registerLazy<ExpensiveService>(() => ExpensiveService());

// Instance is created here, not at registration time
final service = InjectX.get<ExpensiveService>();

Async Registration #

For services that require async creation (e.g., loading config, connecting to a database):

InjectX.registerAsync<DatabaseService>(() async {
  final db = DatabaseService();
  await db.connect();
  return db;
});

// Must use getAsync/injectAsync — sync get throws StateError
final db = await injectAsync<DatabaseService>();

Circular Dependency Detection #

InjectX detects circular get() calls and throws a clear StateError instead of hanging or overflowing the stack:

class A {
  void init() { inject<B>(); }
}
class B {
  void init() { inject<A>(); } // Throws: Circular dependency detected for type A
}

Use the init() pattern to resolve circular dependencies — init() is called after construction, allowing dependencies to be resolved lazily.

API Reference #

Methods #

  • add<T>(T instance): Register an existing instance
  • registerLazy<T>(T Function() factory): Register a factory; instance created on first get
  • registerAsync<T>(Future<T> Function() factory): Register an async factory; use getAsync to retrieve
  • contains<T>(): Check if a type is registered (instance, lazy, or async)
  • get<T>(): Retrieve a registered instance; calls init() if defined (throws if init() fails)
  • getAsync<T>(): Retrieve a registered instance; awaits init() if it's async (throws if init() fails)
  • remove<T>(): Remove a registered dependency and call dispose() if defined
  • length: The number of registered dependencies
  • clear(): Remove all dependencies and dispose each (if supported)

Helper Functions #

  • inject<T>(): Angular-style helper to call InjectX.get<T>()
  • injectAsync<T>(): Angular-style helper for services with async init()

Error Handling #

// Check if a type is registered before accessing it
if (InjectX.contains<MyService>()) {
  final service = InjectX.get<MyService>();
}

// Attempting to retrieve a non-existent dependency
try {
  final service = InjectX.get<UnregisteredService>();
} catch (e) {
  // Throws StateError: No instance registered for type UnregisteredService
}

If an init() method throws, the error propagates to the caller of get<T>() or getAsync<T>().

Best Practices #

  1. Register all dependencies early in your app lifecycle
  2. Use meaningful type parameters for clarity
  3. Implement dispose() for services that require cleanup
  4. Remove services when no longer needed (e.g., on module unload)

Example #

class UserService {
  void dispose() {
    // Cleanup
  }
}

class AuthService {
  final UserService userService;

  AuthService(this.userService);
}

void main() {
  // Register services
  InjectX.add<UserService>(UserService());

  // Register a dependent service
  InjectX.add<AuthService>(AuthService(inject<UserService>()));

  // Use services
  final userService = inject<UserService>();
  final authService = inject<AuthService>();

  // Cleanup
  InjectX.remove<AuthService>();
  InjectX.remove<UserService>();
}

Contributing #

Contributions are welcome! Please feel free to submit a pull request.
For major changes, open an issue first to discuss what you'd like to propose.

License #

This project is licensed under the MIT License — see the LICENSE file for details.

0
likes
160
points
217
downloads

Documentation

API reference

Publisher

verified publisherbabisoft.com

Weekly Downloads

A minimalistic Dependency Injestion solution similar to the Angular one

Repository (GitHub)
View/report issues

License

MIT (license)

More

Packages that depend on inject_x