private static List <SelectedProperty> GetValidProperties <TModel>(
            IWrapRequest <TModel> source,
            Type type,
            List <string> requestProperties,
            string rootName       = null,
            bool isFromCollection = false)
            where TModel : class
        {
            var properties = new List <SelectedProperty>();

            type.GetProperties()
            .Where(property =>
                   !source.IsPropertySuppressedResponse(string.Join(".", TermsHelper.GetTerms(rootName, ".").Union(new List <string> {
                property.Name
            }).Where(term => !string.IsNullOrWhiteSpace(term)))) &&
                   (
                       (requestProperties.Count == 0 && IsToLoadComplexPropertyWhenNotRequested(TypesHelper.TypeIsComplex(property.PropertyType), ConfigurationService.GetConfiguration().ByDefaultLoadComplexProperties, string.IsNullOrWhiteSpace(rootName))) ||
                       (requestProperties.Any(requested => TermsHelper.GetTerms(requested, ".").FirstOrDefault().ToLower().Equals(property.Name.ToLower())))
                   )
                   )
            .ToList()
            .ForEach(property =>
            {
                if (!TypesHelper.TypeIsComplex(property.PropertyType))
                {
                    properties.Add(new SelectedProperty
                    {
                        RequestedPropertyName = string.Join(".", TermsHelper.GetTerms(rootName, ".").Union(new List <string> {
                            property.Name
                        }).Where(term => !string.IsNullOrWhiteSpace(term))),
                        PropertyName     = property.Name,
                        RootPropertyName = rootName,
                        PropertyType     = property.PropertyType,
                        PropertyInfo     = property
                    });
                }
                else if (ConfigurationService.GetConfiguration().ByDefaultLoadComplexProperties)
                {
                    properties.AddRange(
                        GetValidProperties(
                            source,
                            TypesHelper.TypeIsCollection(property.PropertyType) ? property.PropertyType.GetGenericArguments()[0] : property.PropertyType,
                            requestProperties
                            .Where(requested => TermsHelper.GetTerms(requested, ".").FirstOrDefault().ToLower().Equals(property.Name.ToLower()))
                            .Select(requested => string.Join(".", TermsHelper.GetTerms(requested, ".").Skip(1)))
                            .Where(requested => !string.IsNullOrWhiteSpace(requested))
                            .ToList(),
                            string.Join(".", TermsHelper.GetTerms(rootName, ".").Union(new List <string> {
                        property.Name
                    }).Where(term => !string.IsNullOrWhiteSpace(term))),
                            TypesHelper.TypeIsCollection(property.PropertyType)
                            )
                        );
                }
            });

            return(properties);
        }
        private static List <SelectedModel> GetSelectedModelProperties(Type originalRootType, List <SelectedProperty> responseProperties)
        {
            var models = new List <SelectedModel>();

            responseProperties
            .Where(x => !x.RequestedPropertyName.Contains("."))
            .ToList()
            .ForEach(responseProperty =>
                     models.Add(new SelectedModel
            {
                Name                 = responseProperty.PropertyName,
                RequestedName        = responseProperty.RequestedPropertyName,
                OriginalType         = responseProperty.PropertyType,
                OriginalPropertyInfo = responseProperty.PropertyInfo
            }));

            responseProperties
            .Where(x => x.RequestedPropertyName.Contains("."))
            .Select(property =>
            {
                property.RootPropertyName = property.RequestedPropertyName.Split(".")[0];

                return(property);
            })
            .ToList()
            .GroupBy(x => x.RootPropertyName)
            .ToList()
            .ForEach(x =>
            {
                var property = x.FirstOrDefault();
                var originalRootPropertyInfo = (TypesHelper.TypeIsCollection(originalRootType) ? originalRootType.GetGenericArguments()[0] : originalRootType).GetProperty(property.RootPropertyName);
                var originalPropertyType     = originalRootPropertyInfo.PropertyType;
                models.Add(new SelectedModel
                {
                    Name                 = property.RootPropertyName,
                    RequestedName        = property.RootPropertyName,
                    OriginalType         = originalPropertyType,
                    OriginalPropertyInfo = originalRootPropertyInfo,
                    Properties           = GetSelectedModelProperties(originalPropertyType, x.ToList().Select(item =>
                    {
                        item.RootPropertyName      = property.RootPropertyName;
                        item.RequestedPropertyName = item.RequestedPropertyName.Replace($"{property.RootPropertyName}.", "");
                        return(item);
                    }).ToList())
                });
            });

            return(models);
        }