0

我希望能够订阅“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
  }
}
4

1 回答 1

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] 相同。

于 2013-11-11T01:30:50.870 回答