Problem with Dependency Injection and Get It in Flutter
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
Shivam Singh
Updated on December 25, 2022Comments
-
Shivam Singh over 1 year
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?
-
Pieter van Loon over 3 yearsWhy do you want to define both these services as MessageService in getit. How are you want to get one versus the other?
-
Shivam Singh over 3 yearsI thought if we want to extend our application to provide/replace an additional messaging feature, such as SMS then we would just change it in the injector file. And getting dependency by above method is the only way i know. I don't know if it's the correct one. Please tell the correct one if it's not.
-
Shivam Singh over 3 yearsThe both services are defined as MessageService because MyApplication has a dependency of type MessageService. So you have to mention the type of those services. Hence MessageService is provided in get_it.
-
-
Shivam Singh over 3 yearsThanks for the answer.