2017-05-14 2 views
1


Ich bin ziemlich neu zu scala, ich werde schätzen, wenn Sie mir mit der folgenden Frage helfen können.
ich benutze akka-http, um HTTP-Anfrage zu senden Ich möchte eine generische send request-Methode deklarieren, die den HTTP-Antwortkörper mit Unmarshall in den generischen Typ umwandelt.
Wie sollte ich die Unmarshal Reaktion auf T ???Wie entmarschiere ich den generischen Typ, der als Rückgabewert einer Methode verwendet wird?

der Sendeauftrag Umsetzung:

 

    def sendRequest[T](requestMessage :HttpRequestMessage) :Future[T] = 
    { 

     val promise = Promise[HttpResponse]() 
     val request = requestMessage.request -> promise 

     queue.offer(request).flatMap { 
      case QueueOfferResult.Enqueued => promise.future.flatMap[AnyRef] { 
      response => { 
       response.entity.toStrict(FiniteDuration(3,"seconds")).flatMap { 
        strict => Unmarshal(strict.getData).to[T] 
       } 
       } 
      } 
     } 

    } 

Antwort

2

Wenn Sie einen Blick auf dem Code von Unmarshal object nehmen, können Sie die Typ-Parameter verwendet, dass in to eine gewisse Einschränkung haben - einen impliziten Unmarshaller:

class Unmarshal[A](val value: A) { 
    /** 
    * Unmarshals the value to the given Type using the in-scope Unmarshaller. 
    */ 
    def to[B](implicit um: Unmarshaller[A, B], ec: ExecutionContext, mat: Materializer): Future[B] = um(value) 
} 

Wenn ein Wert vom Typ A auf einen Wert vom Typ B unmarshaliert wird, muss ein impliziter Wert vom Typ Unmarshaller[A, B] im Bereich verfügbar sein. Es gibt viele vordefinierte Unmarshaller (z. B. here sind einige, die häufig zum Konvertieren von String in verschiedene Typen wie Int, Boolean usw. verwendet werden), aber Sie können auch eigene definieren. Dies wird als Typklassenmuster bezeichnet.

Wenn Sie möchten, dass Ihr Code für einen Typ T funktioniert, müssen Sie sicherstellen, dass es einen impliziten Unmarshaller für diesen im Bereich verfügbaren Typ gibt. Dies bedeutet, dass Ihre Methode sendRequest einen impliziten Parameter vom Typ haben muss Unmarshaller[Data, T], wo Data sollte, was auch immer ersetzt werden, ist die tatsächliche Art der strict,getData (Ich kann nicht aus dem Code sagen).

So etwas wie folgt aus:

def sendRequest[T](requestMessage: HttpRequestMessage)(implicit m: Unmarshaller[Data, T]): Future[T] // replace Data with concrete type 

Dies ermöglicht die Erstellung von to[T], aber jetzt haben Sie die Pflicht, um tatsächlich an der Stelle der Aufruf von to[T] diesen impliziten Wert in Umfang zu haben. Wie bereits erwähnt, haben Sie zwei Möglichkeiten: entweder vordefinierte Unmarshaller importieren (z. B. PredefinedFromStringUnmarshaller, die weiter oben gezeigt wurden) oder eigene definieren. Ich kann nicht sagen, was T sein kann, so kann ich Sie nicht weiter beraten, aber der Hauptpunkt ist, dass, solange Sie den Unmarshaller für den konkreten Typ hinter T (über den Import oder manuell definieren) bereitstellen, sollte es Arbeit; sonst wird akka keine Ahnung hat, wie Sie zu Ihrem T.

+0

Dank entordnen :) Ihre Erklärung half mir wirklich einen Fortschritt –

+0

@Zfanya Löb Glad zu machen, das zu hören. Da du SO so neu erscheinst, lass mich etwas erklären - jede Frage sollte idealerweise "finalisiert" werden. Dies bedeutet entweder beantwortet oder aus irgendeinem Grund geschlossen. Wenn Sie die benötigte Hilfe erhalten haben, sollten Sie die hilfreichste Antwort akzeptieren, andernfalls können Sie sie bearbeiten und weitere Einzelheiten angeben. Fragen ohne eine akzeptierte Antwort können andere anlocken, die versuchen könnten, Ihnen zu helfen, was eine Zeitverschwendung ist, falls Sie bereits alles haben, was Sie brauchen. Natürlich bleiben viele Fragen unbeantwortet, weshalb beantwortete als solche gekennzeichnet werden sollten. – slouc

Verwandte Themen