1

我正在尝试使用 IoC 框架创建一个非常简单的应用程序,以便 Fantom afIoc熟悉它。我试过这个...

using afIoc

class Main {
  Registry registry := IocService([AppModule#]).start.registry

  @Inject
  myPod::Version? version

  Void main() {
    echo("version is $version")
  }    
}

版本类是

const class Version {
  override Str toStr() {
    "0.0.1"
  }
}

AppModule 是

using afIoc

class AppModule {
  static Void bind(ServiceBinder binder) {
    binder.bind(myPod::Version#)
  }
}

它编译但打印version is null. 我通过重新定义我的 Main 类解决了这个问题:

using afIoc

class Main {

  Registry registry := IocService([AppModule#]).start.registry

  Void main() {
    version := (myPod::Version) registry.serviceById("myPod::Version")
    echo("version is $version")
  }
}

但是我想了解 afIoc Registry 的生命周期,以及为什么没有将 Version 服务注入到我的 Main 类的第一个版本中。谁能解释一下,好吗?

4

1 回答 1

1

我见过人们对其他 IoC 框架提出类似的问题......所以让我们看看运行程序时会发生什么:

using afIoc

class Main {  //................................................... 1
  Registry registry := IocService([AppModule#]).start.registry //.. 2

  @Inject
  myPod::Version? version //....................................... 3

  Void main() {
    echo("version is $version") //................................. 4
  }    
}
  1. Fantom 实例化Main该类。

  2. Fantom 创建registry字段并将其分配给IocService([AppModule#]).start.registry. 该语句只是构建并返回 IoC 注册表。

  3. Fantom 创建version字段并将其默认为null.

  4. Fantom 调用main()打印出 的方法version,即null.

请注意,我们没有要求 IoC干预我们的Main班级。我们刚刚新建了 IoC 注册表并将其设置为一个字段。

如果我们希望 IoC 将值注入到一个类中,我们必须要求它:

  Void main() {
    registry.injectIntoFields(this)

    echo("version is $version")  // --> version is 0.0.1
  }

或者我们可以要求 IoC 为我们实例化一个新的实例Main

registry.autobuild(Main#)

请注意,多次调用autobuild()会创建很多Main.

为了让 IoC 只创建Main(单例)的一个实例,请将其定义为服务AppModule并使用regsitry.serviceById()registry.dependencyByType()- 就像您在Version.

于 2014-08-10T18:25:40.253 回答