1

これらのakkaアクターをバインドするために必要な定型文を減らしたいと思います。

現在、私のコードは次のようになっています。

bind(classOf[ActorRef]).
  annotatedWith(Names.named("mines")).
  toProvider(new TypeLiteral[ActorProvider[MyActor]]() {}).
  asEagerSingleton()

私もそれが次のように見えることを望みます:

bindActor[MyActor].withName("mines")

私はAbstractModuleこの概念を無駄にするためにサブクラス化しようとしました。

関連コード:

class ActorProvider[T <: Actor] @Inject() ( val key:Key[T], val injector:Injector, val system: ActorSystem ) extends Provider[ActorRef] {
  def get = {
    system.actorOf(Props(injector.getInstance(key)))
  }
}
4

2 に答える 2

1

https://github.com/codingwell/scala-guice/をチェックしてください。これを基にしたサンプルです。それは可能にする

bindActor[MyActor].withName("mines")

アクター自体ではなく、非ジェネリックな ActorRef をバインドしていることに注意してください。これにより、@Named("foo") ActorRef のバインディングが作成されます。アクターを直接操作しないでください。

プロバイダでキーを取得できません。プロバイダーは、キーやインジェクション ポイントなどで試したようなコンテキスト インジェクションを行いません。できることは、アクター バインディングごとにプロバイダーの異なるインスタンスを作成し、後でそれを ActorSystem に注入することです。または、API を変更してアクター システム インスタンスも含めることができます。

trait AkkaModule extends AbstractModule {
  // should be:
  // this: AbstractModule =>
  // see http://lampsvn.epfl.ch/trac/scala/ticket/3564
  import ScalaModule._

  private def binderAccess = super.binder // shouldn't need super

  def bindActor[T <: Actor](implicit m: Manifest[T]) = new ActorBindingBuilder {
    //Hack, no easy way to exclude the bind method that gets added to classes inheriting ScalaModule
    //So we experamentally figured out how many calls up is the source, so we use that
    //Commit 52c2e92f8f6131e4a9ea473f58be3e32cd172ce6 has better class exclusion
    val mybinder = binderAccess.withSource((new Throwable).getStackTrace()(3))
    val self = (mybinder bind classOf[ActorRef]).asInstanceOf[AnnotatedBindingBuilder[ActorRef]]
  }

}

object AkkaModule {

  class ActorProvider(val name: String) extends Provider[ActorRef] {
    @Inject var system: ActorSystem = _
    def get = {
      system.actorFor(system.name + "/user/" + name)
    }
  }

  trait ActorBindingBuilder {
    val mybinder: Binder
    val self: AnnotatedBindingBuilder[ActorRef]

    def withName(name: String) = {
      val provider = new ActorProvider(name)
      self.annotatedWith(Names.named(name)).toProvider(provider)
      mybinder.requestInjection(provider)
    }
  }
}
于 2012-12-19T06:58:47.083 に答える
0

scala の型マニフェストを活用するこのようなものは、 http ://www.scala-lang.org/api/current/scala/reflect/Manifest.html で動作する可能性があります。 ここで、Foo は ActorRef に類似し、Bla は MyActor に類似しています。


scala> import com.google.inject
import com.google.inject

scala> val binder:inject.Binder = null
binder: com.google.inject.Binder = null

scala> class Foo {}
defined class Foo

scala> class Bla extends Foo {}
defined class Bla

scala> def bind[T <: Foo:Manifest] = binder.bind( classOf[Foo] ).toProvider( new
 inject.TypeLiteral[inject.Provider[T]](){} ).asEagerSingleton
bind: [T <: Foo](implicit evidence$1: Manifest[T])Unit

おそらく、それを暗黙的な変換と組み合わせて、Binder を MyBinder に変換します: http://daily-scala.blogspot.com/2009/08/implicit-methods.html


class MyBinder {
    def bindActor[T <: ActorRef:Manifest]( nameToBind:String ):Unit = ...
}


object MyBinder {
    implicit def binderToMyBinder( ...
}

幸運を!

于 2012-12-18T19:11:03.137 に答える