Для того, чтобы иметь возможность обрабатывать большие объемы различных типов запросов я создал .proto
файл вроде этого:Обработка грузов различных сообщений-типов во время выполнения в элегантный способ
message Message
{
string typeId = 1;
bytes message = 2;
}
Я добавил typeId
так, что один знает, что фактический protobuf
bytes
представляет. (Самоописывающийся)
Теперь моя проблема заключается в том, чтобы использовать различные «конкретные типы» элегантным способом. (Примечание: Все отлично работает, если я просто использовать в switch-case
-like подход)
Я думал о решении, как это:
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 с продуктом с com.trueaccord.scalapb.Message [_>: tld.test.proto.Message.Test с tld.test.proto.Message.Other <: com.trueaccord.scalapb. GeneratedMessage с продуктом] с com.trueaccord.lenses.Updatable [_>: tld.test.proto.Message.Other с tld.test.proto.Message.Test <: com.trueaccord.scalapb.GeneratedMessage с продуктом] {def companion : Сериализуемый} требуется: _1
насколько я понимаю - поправьте меня здесь, если я ошибаюсь - компилятор не может быть уверен, что здесь, что actualRequest
является «handable» обработчиком. Это означает, что ему не хватает знаний о том, что actualRequest
определенно находится где-то в этом mapper
И ТАКЖЕ, что для него есть handler
.
Это в основном неявное знание, которое получит человек, но компилятор не может сделать вывод.
Итак, как я могу это преодолеть, элегантно?
Да, я хочу, чтобы избежать сопоставления с образцом. Он поставляется с той же стоимостью обслуживания, что и «switch-case». Для новых типов я просто хочу зарегистрировать новые обработчики и карты. – Sorona
@ Sorona, что с предложением HMap будет работать для вас? –
Никогда не использовал 'HMap' раньше и предпочел бы чистое решение Scala без дополнительной зависимости. – Sorona