public static async Task <T> UseService <T>(this IAgentConnectProxyFactory factory,
                                                    Func <Service.AgentConnect, Task <T> > func, Agent agent)
        {
            var success = true;
            var proxy   = factory.CreateProxy();

            try
            {
                using (var scope = new FlowingOperationContextScope(((ClientBase <Service.AgentConnect>)proxy).InnerChannel))
                {
                    AddMessageHeader(agent);

                    AddHttpHeader(agent);

                    return(await func(proxy).ContinueOnScope(scope));
                }
            }
            catch (FaultException <Service.BusinessError> ex)
            {
                // If TryParse fails, ignore it and use default value.
                var errorCodeInt = 0;
                Int32.TryParse(ex.Detail.errorCode, out errorCodeInt);

                // TODO: Best way to do the data copy to new exception??? Extension?
                var acException = new AgentConnectException(ex.Message, ex)
                {
                    ErrorCode      = errorCodeInt,
                    ErrorString    = ex.Detail.messageShort,
                    OffendingField = ex.Detail.offendingField,
                    TimeStamp      = DateTime.Now,
                    DetailString   = ex.Detail.message
                };

                throw acException;
            }
            catch (FaultException <Service.SystemError> ex)
            {
                // If TryParse fails, ignore it and use default value.
                var errorCodeInt = 0;
                Int32.TryParse(ex.Detail.errorCode, out errorCodeInt);

                var subErrorCodeInt = 0;
                Int32.TryParse(ex.Detail.subErrorCode, out subErrorCodeInt);

                // TODO: Best way to do the data copy to new exception??? Extension?
                var acException = new AgentConnectException(ex.Message, ex)
                {
                    ErrorCode    = errorCodeInt,
                    ErrorString  = ex.Detail.errorString,
                    SubErrorCode = subErrorCodeInt,
                    TimeStamp    = ex.Detail.timeStamp,
                    DetailString = ex.Detail.detailString
                };

                throw acException;
            }
            catch (FaultException ex)
            {
                MessageFaultError errObj = null;

                var msgFault = ex.CreateMessageFault();
                if (msgFault.HasDetail)
                {
                    using (var reader = msgFault.GetReaderAtDetailContents())
                    {
                        var ser = new DataContractSerializer(typeof(MessageFaultError));
                        errObj = (MessageFaultError)ser.ReadObject(reader, true);
                    }
                }

                throw new Exception($"FaultException - {errObj?.ErrorString}");
            }
            catch (CommunicationException comsEx)
            {
                // Differnt fatal error exception type?
                throw new Exception("CommunicationException - Unable to call AgentConnect:" + comsEx.Message, comsEx);
            }
            catch (Exception ex)
            {
                success = false;
                throw new Exception("Exception - Unable to call AgentConnect:" + ex.Message, ex);
            }
            finally
            {
                if (proxy is ICommunicationObject)
                {
                    if (!success)
                    {
                        ((ICommunicationObject)proxy).Abort();
                    }
                    else
                    {
                        ((ICommunicationObject)proxy).Close();
                    }
                }
            }
        }
 public static SimpleAwaiter <TResult> ContinueOnScope <TResult>(this Task <TResult> @this, FlowingOperationContextScope scope)
 {
     return(new SimpleAwaiter <TResult>(@this, scope.BeforeAwait, scope.AfterAwait));
 }