jonsamwell / flutter_simple_dependency_injection

A super simple dependency injection implementation for flutter that behaviours like any normal IOC container and does not rely on mirrors
MIT License
94 stars 8 forks source link

DI #7

Closed paul-hammant closed 6 years ago

paul-hammant commented 6 years ago
Injector.getInjector().get<SomeService>().doSomething();

Sorry to be the bearer of bad news but that's inversion of inversion of control. Singletons and ServiceLocators were what we were trying to counter in the first place - IoC and DI were the antidote to SomeClass.getInstance().get("some_key").invokeMethodOnThat(args);

Unless getInjector() gives you a new instance every time you call it, I think we're looking at service-locator :-(

jonsamwell commented 6 years ago

@paul-hammant the get method will give you a new instance every time unless you specify the service as a singleton in the mapping. This library provides the tools for you to handle your services and their dependencies. What I suggest is that you do not use this library explicitly in your code outside of module containers; but rather build containers that configure the injector with services and objects that take their dependencies in as constructor parameters. That way you will NEVER need to use the injector explicitly outside of a container and therein have proper DI. See the naive example below.

import 'package:flutter_simple_dependency_injection/injector.dart';

abstract class Container {
  configure(Injector rootInjector);
}

class SubModuleContainer extends Container {
  @override
  configure(Injector rootInjector) {
    _configureServices(rootInjector);
    _configureBLocs(rootInjector);
    _configurePages(rootInjector);
  }

  _configureServices(Injector rootInjector) {
    rootInjector.map<FileService>((i) => new FileService(), isSingleton: true);
    rootInjector.map<Logger>((i) => new FileLogger(i.get<FileService>()));
  }

  _configureBLocs(Injector rootInjector) {
    rootInjector.map<AuthenticationBLoc>((i) => new AuthenticationBLoc(i.get<FileService>()));
  }

  _configurePages(Injector rootInjector) {
    rootInjector.map<LoginPage>((i) => new LoginPage(i.get<AuthenticationBLoc>()));
  }
}
jonsamwell commented 6 years ago

@paul-hammant this is a good point. While I think people should use this similar to the example I give above it can be used as a naive service locator. I will add and example of the above to help guide people.