protected override async Task <T> InvokeExportAsync <T>(
            NodeInvocationInfo invocationInfo, CancellationToken cancellationToken)
        {
            var payloadJson = JsonConvert.SerializeObject(invocationInfo, jsonSerializerSettings);
            var payload     = new StringContent(payloadJson, Encoding.UTF8, "application/json");
            var response    = await _client.PostAsync(_endpoint, payload, cancellationToken);

            if (!response.IsSuccessStatusCode)
            {
                // Unfortunately there's no true way to cancel ReadAsStringAsync calls, hence AbandonIfCancelled
                var responseJson = await response.Content.ReadAsStringAsync().OrThrowOnCancellation(cancellationToken);

                var responseError = JsonConvert.DeserializeObject <RpcJsonResponse>(responseJson, jsonSerializerSettings);

                throw new NodeInvocationException(responseError.ErrorMessage, responseError.ErrorDetails);
            }

            var responseContentType = response.Content.Headers.ContentType;

            switch (responseContentType.MediaType)
            {
            case "text/plain":
                // String responses can skip JSON encoding/decoding
                if (typeof(T) != typeof(string))
                {
                    throw new ArgumentException(
                              "Node module responded with non-JSON string. This cannot be converted to the requested generic type: " +
                              typeof(T).FullName);
                }

                var responseString = await response.Content.ReadAsStringAsync().OrThrowOnCancellation(cancellationToken);

                return((T)(object)responseString);

            case "application/json":
                var responseJson = await response.Content.ReadAsStringAsync().OrThrowOnCancellation(cancellationToken);

                return(JsonConvert.DeserializeObject <T>(responseJson, jsonSerializerSettings));

            case "application/octet-stream":
                // Streamed responses have to be received as System.IO.Stream instances
                if (typeof(T) != typeof(Stream) && typeof(T) != typeof(object))
                {
                    throw new ArgumentException(
                              "Node module responded with binary stream. This cannot be converted to the requested generic type: " +
                              typeof(T).FullName + ". Instead you must use the generic type System.IO.Stream.");
                }

                return((T)(object)(await response.Content.ReadAsStreamAsync().OrThrowOnCancellation(cancellationToken)));

            default:
                throw new InvalidOperationException("Unexpected response content type: " + responseContentType.MediaType);
            }
        }
 /// <summary>
 /// Asynchronously invokes code in the Node.js instance.
 /// </summary>
 /// <typeparam name="T">The JSON-serializable data type that the Node.js code will asynchronously return.</typeparam>
 /// <param name="invocationInfo">Specifies the Node.js function to be invoked and arguments to be passed to it.</param>
 /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the invocation.</param>
 /// <returns>A <see cref="Task{TResult}"/> representing the completion of the RPC call.</returns>
 protected abstract Task <T> InvokeExportAsync <T>(
     NodeInvocationInfo invocationInfo,
     CancellationToken cancellationToken);