根据您可以或愿意对您的服务做出多少假设,这是一种完全简单的方法,但可能仍然是一种选择。它基本上依赖于 1) 已知所有可能的消息类型和 b) 部分函数仅在一维中是部分的(稍后会详细介绍)。
我们需要一组可能的消息类型:
sealed trait Message
case class Hello(who: String) extends Message
case class Lunch(withWhom: String) extends Message
case class Dinner(withWhom: String) extends Message
case class Goodbye(who: String) extends Message
还有一些示例服务:
val service0: PartialFunction[Any, Unit] = {
case Hello(who) => ()
case Goodbye(who) => ()
}
val service1: PartialFunction[Any, Unit] = {
case Hello(who) => ()
case Lunch(withWhom) => ()
case Goodbye(who) => ()
}
var services = List(service0, service1)
接下来,我们还定义了一个消息实例列表,作为接受消息的蓝图:
val simpleInstances = List(Hello("*"), Lunch("*"), Dinner("*"), Goodbye("*"))
最后,我们定义了一个方法,该方法从偏函数返回接受的参数和可能的参数列表:
def supportedArguments[F, T, A <: F]
(pf: PartialFunction[F, T], args: Iterable[A]) =
args filter pf.isDefinedAt
漂亮的打印机:
def printSupportedArguments(services: Iterable[PartialFunction[Any, Unit]],
messages: Iterable[Message]) {
services.zipWithIndex.foreach {case (s, i) =>
val supported = supportedArguments(s, messages)
println(s"Service $i supports $supported")
}
}
我们走吧:
printSupportedArguments(services, simpleInstances)
// Service 0 supports List(Hello(*), Goodbye(*))
// Service 1 supports List(Hello(*), Lunch(*), Goodbye(*))
// Service 2 supports List(Goodbye(*))
如果服务不仅在它们接受的消息类型上是局部的,而且在它们接受的消息内容方面也是局部的,也就是说,如果它们在多个方向上是局部的,事情就会变得更加复杂:
val service2: PartialFunction[Any, Unit] = {
case Hello("Thomas") => ()
case Hello("Laura") => ()
case Goodbye(who) => ()
}
这样的服务还需要调整蓝图实例列表:
val moreInstances = simpleInstances ++ List(Hello("Thomas"), Hello("Laura"))
导致:
printSupportedArguments(services :+ service2, moreInstances)
// Service 0 supports List(Hello(*), Goodbye(*), Hello(Thomas), Hello(Laura))
// Service 1 supports List(Hello(*), Lunch(*), Goodbye(*), Hello(Thomas),
// Hello(Laura))
// Service 2 supports List(Goodbye(*), Hello(Thomas), Hello(Laura))
这种方法的一系列缺点显然包括以下内容:
如果您找到使用宏或反射(或魔术)的真正解决方案,请在此处发布!