依赖注入的问题及其在 Flutter 中的解决

Shi*_*ngh 3 dependency-injection dart flutter

我一直在学习依赖注入,现在我已经在 dart 中实现了一个示例。但我遇到了 get_it 包的问题。这是代码:

'消息服务.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.");
  }
}
  
Run Code Online (Sandbox Code Playgroud)

'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());
}
Run Code Online (Sandbox Code Playgroud)

'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", "bill@abc.com");
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,当在injection_container.dart中注册EmailServiceImpl和SMSServiceImpl时,它给我错误:未处理的异常:无效的参数:类型为MessageService的对象/工厂已在GetIt内注册。

如果我注释掉 SMSServiceImpl 注册,它就可以正常工作。有人能告诉有什么问题吗?如果有人可以查看我的依赖注入示例,那将会很有帮助。这是呈现依赖注入的正确方式吗?

小智 6

getIt.registerFactory<MessageService>(() => EmailServiceImpl());
getIt.registerFactory<MessageService>(() => SMSServiceImpl());
Run Code Online (Sandbox Code Playgroud)

GetIt 仅允许(默认情况下)一种类型的一个实例。

因此,您的代码尝试注册同一类型(MessageService)的两个实例。来自 GetIt 文档

您必须传递一个工厂函数 func,它返回 T 实现的新实例。每次调用 get() 时,您都会返回一个新实例。

因此,当您调用 GetIt.I.get() 时,它不会知道它是 EmailServiceImpl 还是 SMSServiceImpl

尝试这个

getIt.registerFactory<EmailServiceImpl>(() => EmailServiceImpl());
getIt.registerFactory<SMSServiceImpl>(() => SMSServiceImpl());
Run Code Online (Sandbox Code Playgroud)

您还可以允许重新评估,以便您的代码能够按原样运行。

GetIt.I.allowReassignment = true