Reputation: 117
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
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
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