Shivam Singh
Shivam Singh

Reputation: 117

Problem with Dependency Injection and Get It in Flutter

I have been learning about Dependency Injection and now I have implemented an example in dart. But I'm facing an issue with get_it package. Here's the code:

'MessageService.dart'

abstract class MessageService {
  void sendMessage(String msg, String rec);
}

class EmailServiceImpl implements MessageService {
  @override
  void sendMessage(String message, String receiver) {
    //logic to send email
    print("Email sent to $receiver with message $message.");
  }
}

class SMSServiceImpl implements MessageService {
  @override
  void sendMessage(String message, String receiver) {
    //logic to send SMS
    print("SMS sent to $receiver with message $message.");
  }
}
  

'injection_container.dart'

import 'package:get_it/get_it.dart';

import 'MessageService.dart';
import 'main.dart';

final getIt = GetIt.instance;

void init() async {
  getIt.registerFactory<Client>(() => Client());
  getIt.registerFactory<MyApplication>(() => MyApplication(EmailServiceImpl()));
  getIt.registerFactory<MessageService>(() => EmailServiceImpl());
  getIt.registerFactory<MessageService>(() => SMSServiceImpl());
}

'main.dart'

import 'MessageService.dart';
import 'injection_container.dart' as di;

void main() {
  di.init();
  di.getIt<Client>().send();
}

class MyApplication {
  MessageService _service;

  MyApplication(this._service);

  void processMessages(String msg, String rec) {
    //do some msg validation, manipulation logic etc
    this._service.sendMessage(msg, rec);
  }
}

class Client {
  void send() {
    MyApplication app = di.getIt<MyApplication>();
    app.processMessages("Hi Bill", "[email protected]");
  }
}

But when registering both EmailServiceImpl and SMSServiceImpl in injection_container.dart it gives me in error as : Unhandled Exception: Invalid argument(s): Object/factory with type MessageService is already registered inside GetIt.

If I comment out SMSServiceImpl registration it works fine. Can someone tell what's the problem? And it would be helpful if someone can review my Dependency Injection example. Is it the right way to present Dependency Injection?

Upvotes: 5

Views: 4450

Answers (2)

Evandro Junior
Evandro Junior

Reputation: 548

getIt.registerFactory<MessageService>(() => EmailServiceImpl());
getIt.registerFactory<MessageService>(() => SMSServiceImpl());

GetIt only allows (by default) one instance of a type.

So your code is trying to register two instances of a same type (MessageService). From GetIt doc

You have to pass a factory function func that returns an NEW instance of an implementation of T. Each time you call get() you will get a new instance returned.

So when you call GetIt.I.get() it wont know if it's a EmailServiceImpl or a SMSServiceImpl

Try this

getIt.registerFactory<EmailServiceImpl>(() => EmailServiceImpl());
getIt.registerFactory<SMSServiceImpl>(() => SMSServiceImpl());

You can also allow reassingments so your code will work the way it is.

GetIt.I.allowReassignment = true

Upvotes: 6

ASP
ASP

Reputation: 854

I'd like to point out, that the accepted answer is no longer valid. get_it does allow the registration of multiple instances of a type using "named registration" with the argument instanceName. To quote from the readme:

All registration functions have an optional named parameter instanceName. Providing a name with factory/singleton here registers that instance with that name and a type.

Upvotes: 2

Related Questions