为了能够处理大量不同的请求类型,我创建了一个.proto
这样的文件:
message Message
{
string typeId = 1;
bytes message = 2;
}
我添加了,typeId
以便知道实际protobuf
bytes
代表什么。(自我描述)
现在我的问题是以优雅的方式处理不同的“具体类型”。(注意:如果我简单地使用类似switch-case
的方法,一切正常!)
我想到了这样的解决方案:
1)具有不同处理程序必须实现的特征,例如:
trait Handler[T]
{
def handle(req: T): Any
}
object TestHandler extends Handler[Test]
{
override def handle(req: Test): String =
{
s"A success, $req has been handled by TestHandler
}
}
object OtherHandler extends Handler[Other]
{
override def handle(req: Other): String =
{
s"A success, $req has been handled by OtherHandler
}
}
2) 提供某种注册表来查询给定消息的正确处理程序:
val handlers = Map(
Test -> TestHandler,
Other -> OtherHandler
)
3)如果有请求进来,它会识别自己,所以我们需要另一个 Mapper:
val reqMapper = Map(
"Test" -> Test
"Other" -> Other
)
4)如果有请求进来,处理它:
val request ...
// Determine the requestType
val requestType = reqMapper(request.type)
// Find the correct handler for the requestType
val handler = handlers(requestType)
// Parse the actual request
val actualRequest = requestType.parse(...) // type of actualRequest can only be Test or Other in our little example
现在,直到这里一切看起来都很好,花花公子,但是这条线打破了我的整个世界:
handler.handle(actualRequest)
它导致:
类型不匹配; 发现:com.trueaccord.scalapb.GeneratedMessage 与 Product 与 com.trueaccord.scalapb.Message [_ >: tld.test.proto.Message.Test 与 tld.test.proto.Message.Other <: com.trueaccord.scalapb。 GeneratedMessage with Product] with com.trueaccord.lenses.Updatable[_ >: tld.test.proto.Message.Other with tld.test.proto.Message.Test <: com.trueaccord.scalapb.GeneratedMessage with Product]{def companion :可序列化} 需要:_1
据我了解-如果有误,请在此处纠正我-编译器无法确定此处actualRequest
是否可以由处理程序“处理”。这意味着它缺乏这样的知识,即actualRequest
它肯定存在于其中,而且它mapper
也存在一个handler
。
它基本上是人类可以获得的隐含知识,但编译器无法推断。
那么,话虽这么说,我怎样才能优雅地克服这种情况呢?