private VKBackendResult <T> GetBackendResultFromString <T>(string dataString, Func <string, T> customDeserializationFunc)
        {
            var result = new VKBackendResult <T>();

            result.ResultString = dataString;

            if (dataString.StartsWith(ERROR_PREFIX_GENERAL))
            {
                try
                {
                    result.Error = JsonConvert.DeserializeObject <ErrorRoot>(dataString).error;

                    VKResultCode resultCode = VKResultCode.UnknownError;

                    if (Enum.TryParse <VKResultCode>(result.Error.error_code.ToString(), out resultCode))
                    {
                        result.ResultCode = resultCode;
                    }
                }
                catch (Exception)
                {
                    result.ResultCode = VKResultCode.UnknownError;
                }
            }
            else
            {
                result.ResultCode = VKResultCode.Succeeded;

                if (customDeserializationFunc != null)
                {
                    try
                    {
                        var data = customDeserializationFunc(dataString);
                        result.Data = data;
                    }
                    catch (Exception exc)
                    {
                        Logger.Error("VKRequest custom deserialization function failed on dataString=" + dataString, exc);
                        result.ResultCode = VKResultCode.DeserializationError;
                    }
                }
                else
                {
                    try
                    {
                        var data = JsonConvert.DeserializeObject <GenericRoot <T> >(dataString).response;
                        result.Data = data;
                    }
                    catch (Exception exc)
                    {
                        Logger.Error("VKRequest deserialization failed on dataString=" + dataString, exc);
                        result.ResultCode = VKResultCode.DeserializationError;
                    }
                }
            }
            return(result);
        }
        private void DoDispatch <T>(
            Dictionary <string, string> parametersDict,
            Action <VKBackendResult <T> > callback,
            Func <string, T> customDeserializationFunc = null)
        {
            parametersDict["v"] = VKSDK.API_VERSION;

            var accessToken = VKSDK.GetAccessToken();

            if (accessToken != null)
            {
                parametersDict["access_token"] = accessToken.AccessToken;
            }

            var dispatchUri = string.Format(REQUEST_BASE_URI_FRM, _parameters.MethodName);

            VKHttpRequestHelper.DispatchHTTPRequest(
                dispatchUri,
                parametersDict,
                (httpResult) =>
            {
                if (httpResult.IsSucceeded)
                {
                    var backendResult = GetBackendResultFromString <T>(httpResult.Data, customDeserializationFunc);


                    if (backendResult.ResultCode == VKResultCode.CaptchaRequired)
                    {
                        var captchaRequest = new VKCaptchaUserRequest
                        {
                            CaptchaSid = backendResult.Error.captcha_sid,
                            Url        = backendResult.Error.captcha_img
                        };

                        VKSDK.InvokeCaptchaRequest(captchaRequest,
                                                   (captchaResponse) =>
                        {
                            if (!captchaResponse.IsCancelled)
                            {
                                var parametersWithCaptcha = new Dictionary <string, string>(parametersDict);

                                parametersWithCaptcha["captcha_sid"] = captchaResponse.Request.CaptchaSid;
                                parametersWithCaptcha["captcha_key"] = captchaResponse.EnteredString;

                                DoDispatch(parametersWithCaptcha,
                                           callback,
                                           customDeserializationFunc);
                            }
                            else
                            {
                                InvokeSafely(() => callback(new VKBackendResult <T>()
                                {
                                    ResultCode = VKResultCode.CaptchaControlCancelled
                                }));
                            }
                        });
                    }
                    else if (backendResult.ResultCode == VKResultCode.ValidationRequired)
                    {
                        var validationRequest = new VKValidationRequest
                        {
                            ValidationUri = backendResult.Error.redirect_uri
                        };

                        VKSDK.InvokeValidationRequest(validationRequest,
                                                      (vr) =>
                        {
                            if (vr.IsSucceeded)
                            {
                                DoDispatch(parametersDict, callback, customDeserializationFunc);
                            }
                            else
                            {
                                InvokeSafely(() => callback(new VKBackendResult <T> {
                                    ResultCode = VKResultCode.ValidationCanceslledOrFailed
                                }));
                            }
                        });
                    }
                    else
                    {
                        InvokeSafely(() => callback(backendResult));
                    }
                }
                else
                {
                    var backendResult = new VKBackendResult <T> {
                        ResultCode = VKResultCode.CommunicationFailed
                    };
                    InvokeSafely(() => callback(backendResult));
                }
            });
        }