/// <summary> /// This methods invoke the Method or MethodName via reflection. /// MethodName is used if Method is not defined. /// </summary> /// <returns>Object returned by the Method call if successful; Otherwise will return null.</returns> public async Task <Object> InvokeServiceMethodAsync() { _logger.Debug("Started"); Object ret = null; ServiceProxyEventArgs eventArgs = new ServiceProxyEventArgs { Status = ServiceProxyCallStatus.FailedToSend, MethodName = MethodName }; var methodName = MethodName; try { MethodInfo targetMethod = Method; if (targetMethod == null) { targetMethod = Target.GetType().GetRuntimeMethod(MethodName, Util.GetTypes(Parameters)); } else { methodName = Method.Name; } if (targetMethod != null && Target != null) { _logger.Debug(String.Format("Begin method invoke {0} {1}", MessageId, methodName)); if (targetMethod.ReturnType == (typeof(Task)) || targetMethod.ReturnType.Name == "Task`1") { eventArgs.ReturnValue = await(dynamic) targetMethod.Invoke(Target, Parameters); _logger.Debug("Finished"); } else { //If the target does not return this could block the update and leave this message in transmitting status. eventArgs.ReturnValue = targetMethod.Invoke(Target, Parameters); _logger.Debug("Finished Invoke"); } if (UseGetResult) { _logger.Debug("Getting return value"); eventArgs.ReturnValue = CallGetResult(methodName, eventArgs.ReturnValue); _logger.Debug(string.Format("Return value: {0}", eventArgs.ReturnValue)); } _logger.Debug("Marking status CompletedSuccessfully"); eventArgs.Status = ServiceProxyCallStatus.CompletedSuccessfully; ret = eventArgs.ReturnValue; } else { _logger.Error(string.Format("Method {0} not contained in target {1}", methodName, Target == null ? "Unknown Type" : Target.GetType().FullName)); eventArgs.Status = ServiceProxyCallStatus.NotDestinedForTarget; } } catch (Exception ex) { var errorMessage = string.Empty; var e = ex; while (e != null) { errorMessage += string.Format("(Message = {1} -- Excpetion Type= '{0}'), ", e.GetType().Name, e.Message); e = e.InnerException; } _logger.Error(String.Format("Method invoke messageid={0}, methodnamd={1}, exception {2}, innerExceptions: '{3}'", MessageId, methodName, ex.Message, errorMessage), ex); eventArgs.ReturnValue = null; if (ex is ErrorResponseException || (ex is TargetInvocationException && ex.InnerException is ErrorResponseException)) { _logger.Debug("Sending CompletedWithError status"); eventArgs.Status = ServiceProxyCallStatus.CompletedWithError; } else { eventArgs.Status = ServiceProxyCallStatus.FailedToSend; } if (ex is TargetInvocationException) { eventArgs.ServiceException = ex.InnerException; } else { eventArgs.ServiceException = ex; } } finally { _logger.Debug(String.Format("End method invoke {0} {1}", MessageId, methodName)); if (CallCompleteEventHandler != null) { try { CallCompleteEventHandler(this, eventArgs); } catch (Exception ex) { // don't want listeners exception to affect us. _logger.Error(string.Format("Call Complete Event Listener threw an exception after calling {0}.", methodName), ex); } } } _logger.Debug("Finished"); return(ret); }
/// <summary> /// Completion event for service calls /// </summary> /// <param name="src"></param> /// <param name="args"></param> private void sc_CallCompleteEventHandler(object src, ServiceProxyEventArgs args) { if (src == null) { _logger.Warn("Source object is null skipping processing"); return; } var serviceCall = (ServiceCall)src; serviceCall.CallCompleteEventHandler -= sc_CallCompleteEventHandler; args.CallParameters = serviceCall.Parameters; if (args.Status != ServiceProxyCallStatus.FailedToSend) { _logger.Debug($"CallService completed {serviceCall.MessageId} {serviceCall.MethodName}"); if (CallCompleteEventHandler != null) { try { CallCompleteEventHandler.BeginInvoke(this, args, null, this); } catch (Exception e) { _logger.Warn(e.Message, e); } } } else { _logger.Debug($"CallService Failed to Send. {serviceCall.MessageId} {serviceCall.MethodName}"); } try { var message = Messages.Instance.GetMessage(serviceCall.MessageId); if (serviceCall.RecurringMessageId != Guid.Empty) { Messages.Instance.ResetMessage(message.Id); } else { switch (args.Status) { case ServiceProxyCallStatus.CompletedSuccessfully: Messages.Instance.MarkMessage(message, MessageStatus.Sent); break; case ServiceProxyCallStatus.CompletedWithError: Messages.Instance.MarkMessage(message, MessageStatus.Failed); break; case ServiceProxyCallStatus.FailedToSend: case ServiceProxyCallStatus.NotDestinedForTarget: Messages.Instance.MarkMessage(message, MessageStatus.Incomplete); break; } } } catch (Exception ex) { _logger.Error($"Failed to mark message status {serviceCall.MessageId} {serviceCall.MethodName} {ex.Message}", ex); } }