Syringe ๐Ÿ’‰

Syringe is a dependency injection (DI) library for Dart applications. ๐Ÿš€

Features โœจ

  • Dependency Injection: Easily manage dependencies in your Dart applications using a flexible and intuitive API. ๐Ÿ› ๏ธ
  • Service Locator: Utilize a service locator pattern for creating and resolving objects with dependencies. ๐Ÿ”
  • Module Visibility: Organize your dependencies into modules with customizable visibility settings. ๐Ÿ”’
  • SyringeFactory (Dynamic Factories): Create new instances of objects on-the-fly using dependencies from the graph while respecting privacy rules. โšก
  • Cyclic Dependency Detection: Detect and prevent cyclic dependencies to ensure the stability of your application. ๐Ÿ”„
  • Testable Code: Improve the testability of your codebase by decoupling components and mocking dependencies. ๐Ÿงช

Installation ๐Ÿ“ฆ

To use Syringe in your Dart project, add it to your pubspec.yaml:

dependencies:
  syringe: ^0.9.8

Then, run dart pub get to install the package. ๐Ÿ“ฅ

Usage ๐Ÿ’ก

import 'dart:async';

import 'package:syringe/syringe.dart';

Future<void> main() async {
  // Define modules for dependency injection.
  final modules = <Module>[
    ExportModule<Foo>(
      // Define factory method for Foo using ExportModule.
      onInject: (deps) => Foo(bar: deps<Bar>()),
      dependencies: [Bar], // Dependencies required by Foo.
    ),
    BarModule(), // Module for creating Bar instances.
  ];

  // Create an injector instance.
  final injector = Injector<Dependency>(
    modules: modules, // List of modules to inject.
    onProgress: (info) {
      // Callback to track injection progress.
      if (info.phase == ProgressPhase.done) {
        final total = info.total;
        final type = info.type;
        final current = info.current;
        final percent = info.percent;
        final percentStr = percent.toString().padLeft(3);
        final internalStr = info.export ? 'export' : '';

        // Print progress information.
        print('[$percentStr %] $current of $total ($type) $internalStr');
      }
    },
    onInject: Dependency.onInject, // Callback to create Dependency instances.
  );

  // Perform dependency injection and await the result.
  final dependency = await injector.inject();

  // Print title of the Bar instance associated with Foo.
  print(dependency.foo.bar.title);
}

SyringeFactory โšก

SyringeFactory allows you to create new instances of objects (like ViewModels or Factories) dynamically during the onInject phase. It acts as a controlled Service Locator that only sees exported dependencies.

final result = await Injector<String>(
  modules: [FooModule()], // Assuming Foo is exported
  onInject: (deps) {
    final factory = deps<SyringeFactory>();

    // Create a new instance dynamically
    final myDynamicService = factory.create(
      deps: [Foo],
      onFactory: (factory) => MyDynamicService(factory<Foo>()),
    );

    return myDynamicService.doWork();
  },
).inject();

Note: SyringeFactory will throw SyringeMissingDependencyError if you try to access a dependency that was not marked as export: true in its module. โš ๏ธ

/// Class representing a dependency.
class Dependency {
  final Foo foo;

  /// Factory method to create Dependency instances.
  static Dependency onInject(DepsCallback deps) {
    return Dependency(foo: deps<Foo>());
  }

  const Dependency({required this.foo});
}

/// Class representing a Bar instance.
class Bar {
  final String title;

  Bar({required this.title});
}

/// Class representing a Foo instance.
class Foo {
  final Bar bar;

  const Foo({required this.bar});
}

/// Module for creating Bar instance.
final class BarModule extends Module<Bar> {
  const BarModule();

  @override
  FutureOr<Bar> factory(deps) async {
    // Simulate delay before creating Bar instance.
    await Future.delayed(Duration(seconds: 1));
    return Bar(title: 'Hello World');
  }

  @override
  bool get export => false;
}

Contributing ๐Ÿค

We welcome contributions to the project! If you have any suggestions for improvements or if you find any bugs, please contribute. ๐Ÿ’Ž

License ๐Ÿ“„

This project is licensed under the terms of the MIT License.

Libraries

syringe