我怎样才能按类型进行发布/发布?

时间:2013-11-10 21:48:22

标签: scala akka

我希望能够订阅“Exchange”(类似于在熟悉的情况下在主题交换中通过RabbitMQ中的哈希订阅),之后,发布到给定类型的交换的所有消息都被转发给订户。所以基本上每种类型代表一个渠道。

我已经能够使用案例对象进行测试(只是让它先工作然后重构为正确的设计)。但是使用案例类,我不知道该怎么做。我可以创建一个类的新实例化并将其传入。但是,我想传入类型,而不是它的对象。然后根据类型进行匹配。

我正在考虑传递一个类的对象,并保持它匹配,如果它是相同的类型,但这似乎我只是管道绑在一起,因为我不知道我在做什么。有人有什么建议吗?

describe("Subscribe") {
  it("should add the subscriber to the list of subscribers for the given channel (message type)", LibraryTest) {
    import lib.exchange.ExchangeInterface.{ TestCommand, Subscribe }

    val exchange = TestActorRef(new Exchange)
    val probe = TestProbe()
    exchange ! Subscribe(probe.ref, /*Insert Type Here*/)
    awaitCond(exchange.underlyingActor.subscribers.get(/* Channel/Type */).get.contains(probe.ref))
  }
}

object ExchangeInterface {
  case class Subscribe(subscriber: ActorRef, channel: Command)

  trait Command
  case class TestCommand(message: Any) extends Command
}

class Exchange extends Actor with ActorLogging {
  import ExchangeInterface.{ Command, Subscribe }

  val name = self.path.name
  var subscribers = HashMap[Any, Set[ActorRef]]()
  def receive = {
    case Subscribe(subscriber: ActorRef, channel: Command) => subscribers(channel) += subscriber
  }
}

1 个答案:

答案 0 :(得分:1)

您可以简单地传入类的完全限定名称,而不是传入类型,对象。它应该工作[*],并会简化一些事情:

exchange ! Subscribe(probe.ref, classOf[TestCommand].getName)

[...]

var subscribers = mutable.HashMap[String, Set[ActorRef]]()
def receive = {
  case Subscribe(subscriber: ActorRef, channel: String) => subscribers(channel) += subscriber
}

如果你想要一点类型的安全性,而不是只有弦乐飞来飞去:

case class Channel(name: String)
object Channel{
  def from(clazz: Class[_]) = Channel(clazz.getName)
}

object ExchangeInterface {
  case class Subscribe(subscriber: ActorRef, channel: String)

  trait Command {
    def channel = Channel.from(this.getClass)
  }
  case class TestCommand(message: Any) extends Command
}

class Exchange extends Actor with ActorLogging {
  import ExchangeInterface.Subscribe

  val name = self.path.name
  var subscribers = mutable.HashMap[Channel, Set[ActorRef]]()
  def receive = {
    case Subscribe(subscriber: ActorRef, channel: Channel) => subscribers(channel) += subscriber
  }
}

这为您提供了两种订阅频道的方式:

exchange ! Subscribe(probe.ref, Channel.from(classOf[TestCommand]))

val command = TestCommand("Message")
exchange ! Subscribe(probe.ref, command.channel)

[*]它不适用于在编译时删除其类型的泛型。所以java.util.ArrayList [Int]将与java.util.ArrayList [String]相同。