GetIt not being able to correctly find registered type based on abstract class/interface, but succeeds with concrete class

luissalgadofreire created this issue on 2021-10-25 · The issue is replied 1 times

Context

I am using:

  • Flutter (Channel stable, 2.5.3, on macOS 11.6 20G165 darwin-x64, locale en-US)
  • get_it: ^7.2.0.

I have the following injector which includes the CategoryRepositoryAdapter service (that implements CategoryRepositoryPort):

// injector.dart
final injector = GetIt.instance;

Future<void> initializeDependencies() async {

  // Rest Client
  injector.registerSingleton<Dio>(Dio());

  // Database Client
  final database = await $FloorMoneyDatabase
      .databaseBuilder(kDatabaseName)
      .build();
  injector.registerSingleton<MoneyDatabase>(database);

  // Database Mappers and Repositories
  injector.registerSingleton<CategoryEntityMapper>(
      CategoryEntityMapper()
  );

  injector.registerSingleton<CategoryRepositoryPort>(    // <--- problem is here
      CategoryRepositoryAdapter(injector(), injector())
  );

  // UI Handlers
  injector.registerSingleton<CategoryHandlerPort>(
      CategoryHandler(injector())
  );

  // Blocs
  injector.registerFactory<LocalCategoryBloc>(
        () => LocalCategoryBloc(injector())
  );

}

The class that calls that service looks like this:

// category.handler.dart
class CategoryHandler implements CategoryHandlerPort {
  final CategoryRepositoryPort _repository;  // <--- problem is here

  const CategoryHandler(this._repository);

  Stream<Category?> findAllCategories() {
    ...
  }

  Future<Category?> findCategoryById(int id) {
    ...
  }

  ...

}

And the concrete service to inject looks like this:

// category.repository_adapter.dart
class CategoryRepositoryAdapter implements CategoryRepositoryPort {
  final MoneyDatabase _database;
  final CategoryEntityMapper _map;

  const CategoryRepositoryAdapter(this._database, this._map);

  @override
  Stream<Category> findAllCategories() async* {
    ...
  }

  @override
  Future<Category?> findCategoryById(int id) async {
    ...
  }

  @override
  Future<void> insertCategory(Category category) {
    ...
  }

  @override
  Future<void> removeCategory(Category category) {
    ...
  }

}

Error

When I run the application with the above, I get the error:

Object/factory with  type CategoryRepositoryAdapter is not registered inside GetIt. 
(Did you accidentally do GetIt sl=GetIt.instance(); instead of GetIt sl=GetIt.instance;
Did you forget to register it?)

Workaround

If I register the concrete class, CategoryRepositoryAdapter, instead of the abstract class that it implements, CategoryRepositoryPort, and reference the former in the calling class, all works fine:

// injector.dart
  ...
  injector.registerSingleton<CategoryRepositoryAdapter>(    // <-- changed this to point to concrete class
      CategoryRepositoryAdapter(injector(), injector())
  );
  ...
// category.handler.dart
class CategoryHandler implements CategoryHandlerPort {
  final CategoryRepositoryAdapter _repository;    // <-- changed this to point to concrete class

  const CategoryHandler(this._repository);
  ...

Summary

  • get_it is registering the service successfully when using the concrete class;
  • get_it is NOT registering the service when using the abstract class.

Any clues what might be wrong?

luissalgadofreire wrote this answer on 2021-10-25

Solved. Looking around, I found that I was calling the concrete class CategoryRepositoryAdapter elsewhere; and that was making get_it confused.

Calling the abstract class CategoryRepositoryPort everywhere solved it.

🤔
Didn't find what you were looking for ?
Create your own issue
More Details About Repo
Owner Name fluttercommunity
Repo Name get_it
Full Name fluttercommunity/get_it
Language Dart
Created Date 2018-05-20
Updated Date 2022-01-17
Star Count 849
Watcher Count 10
Fork Count 83
Issue Count 28

YOU MAY BE INTERESTED

Issue Title State Comments Created Date Updated Date Closed Date