modularity_core

pub package pub points

Core implementation of the Modularity framework, providing Dependency Injection (DI) container and Module Lifecycle management.

Features

  • SimpleBinder: A lightweight, platform-agnostic DI container
  • ModuleController: Manages module lifecycle (init, dispose, hot reload)
  • Scoped Injection: Hierarchical injectors with parent/child scopes
  • Import/Export System: Clean separation between public and private dependencies
  • Circular Dependency Detection: Prevents infinite loops in module graphs

Installation

dependencies:
  modularity_core: ^0.0.1

Usage

Defining a Module

import 'package:modularity_core/modularity_core.dart';

class AuthModule extends Module {
  @override
  void binds(Binder binder) {
    // Private dependencies (internal to module)
    binder.registerLazySingleton<AuthRepository>(() => AuthRepositoryImpl());
    binder.registerLazySingleton<AuthService>(
      () => AuthService(binder.get<AuthRepository>()),
    );
  }
  
  @override
  void exports(Binder binder) {
    // Public dependencies (available to importers)
    binder.registerLazySingleton<AuthService>(() => binder.get<AuthService>());
  }
}

Using ModuleController

void main() async {
  final registry = <Type, ModuleController>{};
  
  final controller = ModuleController(AuthModule());
  
  await controller.initialize(registry);
  
  final authService = controller.binder.get<AuthService>();
  
  // Cleanup
  await controller.dispose();
}

Module Imports

class ProfileModule extends Module {
  @override
  List<Module> get imports => [AuthModule()];
  
  @override
  List<Type> get expects => [AuthService]; // Validates imports
  
  @override
  void binds(Binder binder) {
    final authService = binder.get<AuthService>(); // From AuthModule
    binder.registerLazySingleton<ProfileService>(
      () => ProfileService(authService),
    );
  }
}

Lifecycle Hooks

class MyModule extends Module {
  @override
  void binds(Binder binder) { /* ... */ }
  
  @override
  Future<void> onInit() async {
    // Called after binds() and exports()
    print('Module initialized');
  }
  
  @override
  Future<void> onDispose() async {
    // Called on dispose
    print('Module disposed');
  }
}

Hot Reload Support

// Rebind all dependencies without recreating the controller
controller.hotReload();

Interceptors

class LoggingInterceptor implements ModuleInterceptor {
  @override
  void onInit(Module module) => print('Init: ${module.runtimeType}');
  
  @override
  void onLoaded(Module module) => print('Loaded: ${module.runtimeType}');
  
  @override
  void onError(Module module, Object error) => print('Error: $error');
  
  @override
  void onDispose(Module module) => print('Disposed: ${module.runtimeType}');
}

final controller = ModuleController(
  MyModule(),
  interceptors: [LoggingInterceptor()],
);

SimpleBinder API

Method Description
registerFactory<T>() New instance each call
registerLazySingleton<T>() Single instance, created on first access
registerSingleton<T>() Single instance, created immediately
get<T>() Get dependency (throws if not found)
tryGet<T>() Get dependency (returns null if not found)
parent<T>() Get from parent scope only

License

MIT License - see LICENSE for details.

Libraries

modularity_core