injectable 0.1.0 copy "injectable: ^0.1.0" to clipboard
injectable: ^0.1.0 copied to clipboard

outdated

Injectable is a convenient code generator for [get_it](https://pub.dev/packages/get_it). Inspired by Angular DI, Guice DI and inject.dart.

injectable #

Injectable is a convenient code generator for get_it. Inspired by Angular DI, Guice DI and inject.dart.


Installation #

dependencies:
  # add injectable to your dependencies
  injectable:
  # add get_it
  get_It:

dev_dependencies:
  # add the generator to your dev_dependencies
  injectable_generator:
  # of course build_runner is needed to run the generator
  build_runner:

Setup #


1- Create a new dart file and define a top-level function (lets call it configure) then annotate it with @injectableInit. 2- Call the Generated func $initGetIt() inside your confiugre func.

@injectableInit
void configure() => $initGetIt();

3- Call configure() in your main func before running the App

void main() {
 configure();
 runApp(MyApp());
}

Registering factories #


All you have to do now is annotate your injectable classes with @injectable and let the generator do the work.

@injectable
class ServiceA {}

@injectable
class ServiceB {
    ServiceB(ServiceA serviceA);
}

Run the generator #

Use the [watch] flag to watch the files system for edits and rebuild as necessary.

flutter packages pub run build_runner watch

if you want the generator to run one time and exits use

flutter packages pub run build_runner build

Inside of the generated file #

Injectable will generate the needed register functions for you

final getIt = GetIt.instance;

void $initGetIt({String environment}) {
  getIt..registerFactory<ServiceA>(() => ServiceA())
       ..registerFactory<ServiceB>(ServiceA(getIt<ServiceA>()))
}

Registering singletons #


Simply add the @singleton or @lazySingleton annotations to your class. Alternatively use the constructor version to pass signalsReady to getIt.registerSingleton(signalsReady) @Singleton(signalsReady: true) >> getIt.registerSingleton(Model(), signalsReady: true) @Singleton.lazy(signalsReady: true) >> getIt.registerLazySingleton(() => Model(), signalsReady: true)

@singleton // or @lazySingleton
@injectable
class ApiProvider {}

Binding abstract classes to implementations #


Use the @Bind annotation to bind abstract types to their implementations. Note: the passed type needs to implement or extend the annotated type.

@Bind.toType(ServiceImpl)
@injectable
abstract class Service {}

Generated code for the Above example

getIt.registerFactory<Service>(() => ServiceImpl())

Binding an abstract class to multiable implementations #

Since we can't use type binding to register more than one implementation, we have to use names (tags) to register our instances.

@Bind.toNamedType(ServiceImpl1, name: 'impl1')
@Bind.toNamedType(ServiceImpl2, name: 'impl2')
@injectable
abstract class Service {}

Next annotate the injected instance with @Named() right in the construcor and pass in the name of the desired implementation.

@injectable
class MyRepo {
   final Service service;
    MyRepo(@Named('impl1') this.service)
}

Generated code for the Above example

getIt.registerFactory<Service>(() => ServiceImpl1(), instanceName: 'impl1')
getIt.registerFactory<Service>(() => ServiceImpl2(), instanceName: 'impl2')

getIt.registerFactory<MyRepo>(() => MyRepo(getIt('impl1'))

Auto Tagging #

if you don't pass a name to Bind.toNamedType() the implementation type name will be used @Bind.toNamedType(ServiceImpl1) == @Bind.toNamedType(ServiceImpl1, name: 'ServiceImpl1') Then use @Named.from(Type) annotation to extract the name from the type

@Bind.toNamedType(ServiceImpl1)
@injectable
abstract class Service {}

@injectable
class MyRepo {
   final Service service;
    MyRepo(@Named.from(ServiceImpl1) this.service)
}

Generated code for the Above example

getIt.registerFactory<Service>(() => ServiceImpl1(), instanceName: 'ServiceImpl1')
getIt.registerFactory<MyRepo>(() => MyRepo(getIt('ServiceImpl1'))

Register under different environments #


it is possible to register different dependencies for different environments by using @Environment('name') annotation. in the below example ServiceA is now only registered if we pass the environment name to $initGetIt(envirnoment: 'dev')

@Environment("dev")
@injectable
class ServiceA {}

Generated code for the Above example

void $initGetIt({String environment}) {
 // ... other deps
  if (environment == 'dev') {
    _registerDevDependencies();
  }
}

Usually you would want to register a diffirent implmenetation for the same abstract class under diffrent envirnoments. to do that pass your environment name to the Bind annotation

@Bind.toType(FakeServiceImple, env: 'dev')
@Bind.toType(RealServiceImple, env: 'prod')
@injectable
abstract class Service {}

Generated code for the Above example

void $initGetIt({String environment}) {
// ..other deps
  if (environment == 'dev') {
    _registerDevDependencies();
  }
  if (environment == 'prod') {
    _registerProdDependencies();
  }
}

void _registerDevDependencies() {
  getIt.registerFactory<Service>(() => FakeServiceImple());
  // ..other dev deps
}

void _registerProdDependencies() {
  getIt.registerFactory<Service>(() => RealServiceImple());
    // ..other prod deps
}

Auto registering $Experimental$ #


Instead of annotating every single injectable class you write, it is possible to use a Convention Based Configruation to auto register your injectable classes, espeically if you follow a consice naming convention.

for example you can tell the generator to auto-register any class that ends with Service, Repository or Bloc using a simple regex pattern class_name_pattern: 'Service$|Repository$|Bloc$' To use auto-register create a file with the name build.yaml in the same directory as pubspec.yaml and add

targets:
  $default:
    builders:
      injectable_generator:injectable_builder:
        options:
          auto_register: true
          # auto register any class with a name matches the given pattern
          class_name_pattern:
            "Service$|Repository$|Bloc$"
            # auto register any class inside a file with a
            # name matches the given pattern
          file_name_pattern: "_service$|_repository$|_bloc$"

Problems with the generation? #


Make sure you always Save your files before running the generator, if that doesn't work you can always try to clean and rebuild.

flutter packages pub run build_runner clean

Support the Library #

  • You can support the library by staring in on Github or report any bugs you encounter.
  • also you have a suggestion or think something can be implemented in a better way, open an issue and lets talk about it.
1157
likes
0
pub points
99%
popularity

Publisher

verified publishercodeness.ly

Injectable is a convenient code generator for [get_it](https://pub.dev/packages/get_it). Inspired by Angular DI, Guice DI and inject.dart.

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

flutter

More

Packages that depend on injectable