/// <summary>
        /// Dispatches a <see cref="Request"/> on the given network.
        /// </summary>
        /// <param name="request">Request to be dispatched.</param>
        /// <param name="networkName">Current network name.</param>
        /// <returns>DispatchResult with the corresponding result of the dispatching process.</returns>
        public virtual DispatchResult Dispatch(Request request, string networkName)
        {
            IProxyFactory factory = null;

            if (request.Behavior.ProxyFactoryType == null)
            {
                throw new ArgumentNullException("request.Behavior.ProxyFactoryType");
            }
            try
            {
                factory = (IProxyFactory)Activator.CreateInstance(request.Behavior.ProxyFactoryType);
            }
            catch
            {
                return(DispatchResult.Failed);
            }

            object onlineProxy = factory.GetOnlineProxy(request, networkName);

            if (onlineProxy == null)
            {
                return(DispatchResult.Failed);
            }

            DispatchResult?dispatchResult = null;
            int            retries        = 0;

            try
            {
                while (dispatchResult == null)
                {
                    Exception exception = null;
                    try
                    {
                        retries++;
                        object result = factory.CallOnlineProxyMethod(onlineProxy, request, ref exception);

                        try
                        {
                            // Proxy method call went ok, call the return command
                            InvokeReturnCommand(onlineProxy, request, result);
                        }
                        catch (Exception ex)
                        {
                            if (ex is TargetInvocationException)
                            {
                                throw new ReturnCallbackException(Resources.ExceptionOnReturnCallback + ex.Message, ex.InnerException);
                            }
                            else
                            {
                                throw new ReturnCallbackException(Resources.ExceptionOnReturnCallback + ex.Message, ex);
                            }
                        }

                        dispatchResult = DispatchResult.Succeeded;
                        break;
                    }

                    catch (OnlineProxyException ex)
                    {
                        throw ex.InnerException;
                    }

                    catch (TargetInvocationException ex)
                    {
                        exception = ex.InnerException;
                    }

                    catch (Exception ex)
                    {
                        exception = ex;
                    }

                    if (exception != null)
                    {
                        // Call the exception callback
                        try
                        {
                            switch (InvokeExceptionCommand(request, exception))
                            {
                            case OnExceptionAction.Dismiss:
                                dispatchResult = DispatchResult.Failed;
                                break;

                            case OnExceptionAction.Retry:
                                if (retries >= request.Behavior.MaxRetries)
                                {
                                    dispatchResult = DispatchResult.Failed;
                                }
                                break;
                            }
                        }
                        catch
                        {
                            dispatchResult = DispatchResult.Failed;
                        }
                    }
                }
            }
            finally
            {
                factory.ReleaseOnlineProxy(onlineProxy);
            }

            return((DispatchResult)dispatchResult);
        }