/// <summary>
        ///     create http query string based on properties
        /// </summary>
        /// <param name="obj">base object</param>
        /// <param name="option">formatting options(datetime)</param>
        /// <returns>http query string</returns>
        public static string ToQueryString(this object obj, HttpQueryStringOption option = null)
        {
            var properties = obj.GetType()
                             .GetProperties()
                             .Where(p => p.GetValue(obj, null) != null)
                             .ToList();

            if (properties.IsNullOrEmpty())
            {
                return("");
            }

            var queries = new List <string>();

            if (option.IsNotNull())
            {
                var timeQuery = GetTimeQuery(obj, ref properties, option);
                if (timeQuery.IsNotNullOrEmptyOrWhiteSpace())
                {
                    queries.Add(timeQuery);
                }
            }


            var arrayQuery = GetArrayQuery(obj, ref properties);

            if (arrayQuery.IsNotNullOrEmptyOrWhiteSpace())
            {
                queries.Add(arrayQuery);
            }

            var enumQuery = GetEnumQuery(obj, ref properties);

            if (enumQuery.IsNotNullOrEmptyOrWhiteSpace())
            {
                queries.Add(enumQuery);
            }

            var parametersQuery = GetPropertiesQuery(obj, properties);

            if (parametersQuery.IsNotNullOrEmptyOrWhiteSpace())
            {
                queries.Add(parametersQuery);
            }


            return(queries.Join("&"));
        }
        private static string GetTimeQuery(object obj, ref List <PropertyInfo> properties, HttpQueryStringOption option)
        {
            var parameters = properties.Where(p =>
                                              p.PropertyType == typeof(DateTime) ||
                                              p.PropertyType == typeof(DateTime?) ||
                                              p.PropertyType == typeof(DateTimeOffset) ||
                                              p.PropertyType == typeof(DateTimeOffset?)
                                              )
                             .ToList();


            properties = properties.Except(parameters).ToList();


            var queryItems = new List <string>();


            foreach (var parameter in parameters)
            {
                var queryItem = string.Empty;
                var value     = parameter.GetValue(obj);
                if (value is DateTime? && value.IsNotNull())
                {
                    var nullableDt = (DateTime)value;
                    queryItem = $"{parameter.Name}={HttpUtility.UrlEncode(nullableDt.ToString(option.DateTimeFormat))}";
                }
                else
                {
                    queryItem = value switch
                    {
                        DateTimeOffset nullableOffset when nullableOffset.IsNotNull() =>
                        $"{parameter.Name}={HttpUtility.UrlEncode(nullableOffset.ToString(option.DateTimeFormat))}",
                        DateTime dt =>
                        $"{parameter.Name}={HttpUtility.UrlEncode(dt.ToString(option.DateTimeFormat))}",
                        DateTimeOffset offset =>
                        $"{parameter.Name}={HttpUtility.UrlEncode(offset.ToString(option.DateTimeFormat))}",
                                       _ => queryItem
                    };
                }

                queryItems.Add(queryItem);
            }

            return(queryItems.Join("&"));
        }