2

メッセージハンドラの部分関数で型情報を保持することは可能ですか?

いくつかの特定のパラメーターでイベントに一致する部分関数 eventHandler があります。

  def eventHandler: Receive = {
    case event: Event ⇒
        ...
        val matchingReactions = projectConfiguration.reactions.filter(reaction ⇒ reaction.eventSelector.matches(event))

Match メソッドは、リフレクションを通じて一連のルールに対してイベントを検証します。

case class EventSelector(ops: List[FieldEventSelectorOp]) {
  def matches[T <: Event](event: T)(implicit tag: ru.TypeTag[T], classtag: ClassTag[T]): Boolean = {
    ops.map {
      op ⇒ op.matches(event)
    }.reduceLeft(_ & _)
  }
}

case class FieldEventSelectorOp(field: String, operation: Symbol, value: Any) { 
  def matches[T <: Event](event: T)(implicit tag: ru.TypeTag[T], classtag: ClassTag[T]): Boolean = {
...
}

したがって、match メソッドの TypeTag を確認すると、イベントのサブクラスではなくイベントのみが返されます。完全な型情報を渡すにはどうすればよいですか?

アップデート:

イベントのケース クラス階層:

trait Event {
  def eventType: String
  def eventName: String = this.getClass.getSimpleName
}

trait VCSEvent extends Event {
  def eventType: String = "VCS"
}

case class BranchAdded(branch: String) extends VCSEvent
case class TagAdded(tag: String, commitId: String) extends VCSEvent

具体的なマッチャー:

case class FieldEventSelectorOp(field: String, operation: Symbol, value: Any) extends EventSelectorOp {
  def matches[T <: Event](event: T)(implicit tag: ru.TypeTag[T], classtag: ClassTag[T]): Boolean = {
    val mirror = ru.runtimeMirror(event.getClass.getClassLoader)
    val memberSymbol = tag.tpe.member(ru.newTermName(field))

    if (memberSymbol.name.decoded.equals("<none>"))
      return false

    val fieldValue = if (memberSymbol.isMethod) {
      mirror.reflect(event).reflectMethod(memberSymbol.asMethod).apply()
    } else {
      mirror.reflect(event).reflectField(memberSymbol.asTerm).get
    }

    operation match {
      case 'eq ⇒ fieldValue.equals(value)
      case _   ⇒ false
    }
  }
}
4

1 に答える 1