public object Clone()
		{
			var newParams = new ApiRequestParam(
				this.Method,
				new Dictionary<string, string>( this.Params.Count )
			);

			foreach (var item in this.Params)
				newParams.Params.Add(item.Key, item.Value);

			return newParams;
		}
        protected override object modifyResult(object Data, ApiRequestParam requestParam)
        {
            if (requestParam.Method == "users.getSubscriptions")
            {
                var data = Data as VkUserSubscriptions;

                data.Id = Int32.Parse(requestParam.Params["user_id"]);

                return data;
            }

            if (requestParam.Method == "groups.getMembers")
            {
                var res = new VkGroupMembers();

                res.GroupId = Int32.Parse(requestParam.Params["group_id"]);
                res.GroupMembers = ((IEnumerable)Data).Cast<long>().ToList();

                return res;
            }
            if (requestParam.Method == "friends.get")
            {
                var res = new VkFriends();

                res.UserId = Int32.Parse(requestParam.Params["user_id"]);
                res.Friends = ((IEnumerable)Data).Cast<long>().ToList();

                return res;
            }
            if (requestParam.Method == "groups.get")
            {
                var res = new VkUserGroups();

                res.UserId = Int32.Parse(requestParam.Params["user_id"]);
                res.Groups = ((IEnumerable)Data).Cast<long>().ToList();

                return res;
            }
            if (requestParam.Method == "wall.getComments")
            {
                var res = new VkWallComments();

                res.OwnerId = Int32.Parse(requestParam.Params["owner_id"]);
                res.PostId = Int32.Parse(requestParam.Params["post_id"]);
                res.Comments = ((IEnumerable)Data).Cast<VkComment>().ToList();

                return res;
            }

            return Data;
        }
		protected async Task<object> executeRequest(ApiRequestParam param)
		{
			var needObjectType = getObjectTypeForMethod(param.Method);

			var rawData = await api.ExecuteRequest(param.Method, param.Params);

			object result;
			var requestType = this.GetRequestType(param.Method);
			if (requestType == ApiRequestType.ObjectInfo)
			{
				result = dataExtractor.GetItem(rawData, needObjectType);
			}
			else
			{
				result = dataExtractor.GetItems(rawData, needObjectType);
			}

			return result;
		}
		protected ApiRequestParam createRequestParam(string Method)
		{
			var parameters = getRequestParams(Method);

			var req = new ApiRequestParam(Method, parameters);

			return req;
		}
		protected abstract object modifyResult(object Data, ApiRequestParam requestParam);
		protected abstract void setIdParams(ApiRequestParam requestParam, List<string> ids);
		protected abstract void setIdParams(ApiRequestParam requestParam, string id);
		protected abstract void setListParams(ApiRequestParam requestParam, int Offset, int Count);
 protected override void setListParams(ApiRequestParam requestParam, int Offset, int Count)
 {
     if (Count != 0)
     {
         requestParam.Params["offset"] = Offset.ToString();
         requestParam.Params["count"] = Count.ToString();
     }
 }
 protected override void setIdParams(ApiRequestParam requestParam, List<string> ids)
 {
     switch (requestParam.Method)
     {
         case "groups.getById":
             requestParam.Params["group_ids"] = String.Join(",", ids);
             break;
         case "users.get":
             requestParam.Params["user_ids"] = String.Join(",", ids);
             break;
         default:
             throw new NotSupportedException("Method `" + requestParam.Method + "` is not supported!");
     }
 }
        protected override void setIdParams(ApiRequestParam requestParam, string id)
        {
            string[] ids;
            switch (requestParam.Method)
            {
                case "groups.getById":
                    requestParam.Params["group_id"] = id;
                    break;
                case "groups.get":
                    requestParam.Params["user_id"] = id;
                    break;
                case "groups.getMembers":
                    requestParam.Params["group_id"] = id;
                    break;
                case "users.getSubscriptions":
                    requestParam.Params["user_id"] = id;
                    break;
                case "users.get":
                    requestParam.Params["user_ids"] = id;
                    break;
                case "wall.get":
                    long lId;
                    if (long.TryParse(id, out lId))
                        requestParam.Params["owner_id"] = lId.ToString();
                    else
                        requestParam.Params["domain"] = id;
                    break;
                case "wall.getReposts":
                    ids = id.Split('_'); // 0 - owner_id, 1 - post_id
                    requestParam.Params["owner_id"] = ids[0];
                    requestParam.Params["post_id"] = ids[1];
                    break;
                case "wall.getComments":
                    ids = id.Split('_'); // 0 - owner_id, 1 - post_id
                    requestParam.Params["owner_id"] = ids[0];
                    requestParam.Params["post_id"] = ids[1];
                    break;
                case "friends.get":
                    requestParam.Params["user_id"] = id;
                    break;

                default:
                    throw new NotSupportedException("Method `" + requestParam.Method + "` is not supported!");
            }
        }