public static RemoteException Create(Exception exception, RmiRequestDto body) {
    var sb = new StringBuilder();
    sb.AppendLine("== Courier-Proxied Remote Exception ==");
    sb.AppendLine("RequestId = " + body.InvocationId);
    sb.AppendLine("ServiceId = " + body.ServiceId);
    sb.AppendLine("Method = " + body.MethodName + "<" + body.MethodGenericArguments.Join(", ") + ">");
    sb.AppendLine("Exception = ...");
    sb.AppendLine(exception.ToString());
    sb.AppendLine();
    return new RemoteException(sb.ToString());
 }
      public async Task<RmiResponseDto> Invoke(RemoveServiceInfo serviceInfo, MethodInfo methodInfo, object[] methodArguments) {
         var invocationId = Guid.NewGuid();
         var request = new RmiRequestDto {
            InvocationId = invocationId,
            MethodArguments = methodArguments,
            MethodGenericArguments = methodInfo.GetGenericArguments(),
            MethodName = methodInfo.Name,
            ServiceId = serviceInfo.ServiceId
         };

         if (logger.IsDebugEnabled) {
            logger.Debug($"Sending RMI {invocationId.ToString("n").Substring(0, 6)} Request on method {methodInfo.Name} for service {serviceInfo.ServiceType.Name}. Local: {localIdentity.Id.ToString("n").Substring(0, 6)}, Remote: {serviceInfo.Peer.Identity.Id.ToString("n").Substring(0, 6)}");
         }

         if (localIdentity.Id == serviceInfo.Peer.Identity.Id) {
            if (logger.IsErrorEnabled) {
               logger.Error($"Swallowing as routed to self - RMI {invocationId.ToString("n").Substring(0, 6)} Request on method {methodInfo.Name} for service {serviceInfo.ServiceType.Name}. Local: {localIdentity.Id.ToString("n").Substring(0, 6)}, Remote: {serviceInfo.Peer.Identity.Id.ToString("n").Substring(0, 6)}");
            }
            throw new ArgumentException("Attempted to perform remote service invocation on self.");
         }

         var responseBox = new AsyncBox<RmiResponseDto>();
         responseBoxes.AddOrThrow(invocationId, responseBox);

         await messenger.SendReliableAsync(request, serviceInfo.Peer.Identity.Id).ConfigureAwait(false);

         if (logger.IsDebugEnabled) {
            logger.Debug($"Sent RMI {invocationId.ToString("n").Substring(0, 6)} Request on method {methodInfo.Name} for service {serviceInfo.ServiceType.Name}");
         }

         // response box removed by HandleInvocationResponse - don't cleanup
         var result = await responseBox.GetResultAsync().ConfigureAwait(false);

         if (logger.IsDebugEnabled) {
            logger.Debug($"Received RMI {invocationId.ToString("n").Substring(0, 6)} Response on method {methodInfo.Name} for service {serviceInfo.ServiceType.Name}");
         }
         return result;
      }
 public static string GenerateErrorMessage(RmiRequestDto request) {
    return $"Service of guid {request.ServiceId} unavailable (attempting to invoke method {request.MethodName}).";
 }
 public ServiceUnavailableException(RmiRequestDto request) : base(GenerateErrorMessage(request)) {
 }