Flutter Injectable:通过注释注入泛型类型的多个实例

问题描述 投票:0回答:1

我在我的 flutter 项目中使用 get_it 进行依赖注入。 现在我尝试使用可注入来用注释替换我的手写依赖文件。

我有一个特殊情况,我有一个通用类,必须使用不同的 T 值注入 3 次。

class TestBloc<T> {
    ...
}

这就是我旧配置中的样子:

sl.registerFactory(() => TestBloc<One>(...);
sl.registerFactory(() => TestBloc<Two>(...);
sl.registerFactory(() => TestBloc<Three>(...);

如何对课程进行注释才能使其发挥作用?

当我添加@injectable

@injectable
class TestBloc<T> {
    ...
}

我明白了(当然):

gh.factory<_i34.TestBloc<dynamic>>(() =>_i34.TestBloc<dynamic>(...);

如何注释才能得到这个?

gh.factory<_i34.TestBloc<One>>(() =>_i34.TestBloc<One>(...);
gh.factory<_i34.TestBloc<Two>>(() =>_i34.TestBloc<Two>(...);
gh.factory<_i34.TestBloc<Three>>(() =>_i34.TestBloc<Three>(...);
flutter generics dependency-injection injectable
1个回答
0
投票

我遇到了同样的问题,我想出的解决方案可以解决问题。您必须为具有通用类型的视图模型创建一个工厂。在里面您可以请求您需要的所有泛型类型的依赖项。不幸的是,您必须手动构建所有依赖项。但本质上它与绑定相同。接下来,您必须为您的特定类型扩展工厂。这将确保填充所有必需的类型。然后编译器可以搜索这些类型。美妙之处在于,对于您类型的每个变体,您都可以覆盖一些绑定。如果你真的想要,你还可以提供工厂的不同实现。 小例子:

abstract class StdOutUseCase<T> {
  void printEmpty();
}

mixin Arbitrary<T> {
  T call(Random random);
}

mixin Empty<T> {
  T call();
}

class MockViewModel<T> {
  final StdOutUseCase<T> stdOutUseCase;

  MockViewModel(this.stdOutUseCase);

  void onButtonClick() {
    stdOutUseCase.printEmpty();
  }
}

@Injectable(as: Empty<String>)
class StringEmpty with Empty<String> {
  @override
  String call() {
    return "";
  }
}

@Injectable(as: Arbitrary<String>)
class ArbString with Arbitrary<String> {
  static const adjectives = ["happy", "smart", "cool", "cold"];
  static const nouns = ["fox", "bear", "gorilla"];

  @override
  String call(Random random) {
    return "${adjectives[random.nextInt(adjectives.length)]} ${nouns[random.nextInt(nouns.length)]}";
  }
}

@Injectable(as: Factory<MockViewModel<String>>)
class StringFactory extends MockVMFactory<String> {
  StringFactory(super.empty, super.arbitrary);
}

mixin Factory<T>{
  T call();
}


class MockVMFactory<T> with Factory<MockViewModel<T>> {
  final Empty<T> empty;
  final Arbitrary<T> arbitrary;

  MockVMFactory(this.empty, this.arbitrary);

  @override
  MockViewModel<T> call() => MockViewModel(useCase());

  StdOutUseCase<T> useCase() => FancyStdOutUseCase(empty, arbitrary);
}

class FancyStdOutUseCase<T> extends StdOutUseCase<T> {
  final Empty<T> empty;
  final Arbitrary<T> arbitrary;

  FancyStdOutUseCase(this.empty, this.arbitrary);

  @override
  void printEmpty() {
    print("Empty is ${empty()} and random is ${arbitrary(Random())}");
  }
}

class BaseStdOutUseCase<T> extends StdOutUseCase<T> {
  final Empty<T> empty;

  @inject
  BaseStdOutUseCase(this.empty);

  @override
  void printEmpty() {
    print("Empty for $T is ${empty()}");
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.