private static object GetConvertedSearchValue(PropertyInfo propertyInfo, FieldComparer fieldComparer)
        {
            Type propertyType = propertyInfo.PropertyType;

            if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                if (fieldComparer.CompareValue == null)
                {
                    return(null);
                }

                propertyType = propertyType.GetGenericArguments()[0];
            }

            if (propertyType == typeof(DateTime))
            {
                DateTime dateTime;
                if (DateTime.TryParseExact(
                        fieldComparer.CompareValue,
                        new[] { DATE_TIME_FORMAT, FormatStrings.DATE_AND_TIME_WITH_MILLISECONDS, FormatStrings.UTC_DATE_AND_TIME_WITH_MILLISECONDS },
                        null,
                        DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal,
                        out dateTime))
                {
                    return(dateTime);
                }

                throw new FormatException($"The string '{fieldComparer.CompareValue}' cannot be parsed to DateTime. Expected format is '{DATE_TIME_FORMAT}'.");
            }

            TypeConverter converter = TypeDescriptor.GetConverter(propertyType);

            return(converter.ConvertFrom(fieldComparer.CompareValue));
        }
        private static void AppendFieldComparers <TItem>(FieldComparerGroup <TItem> sourceFieldComparerGroup, FieldComparerGroup destinationFieldComparerGroup)
            where TItem : class
        {
            if ((sourceFieldComparerGroup.Terms.Count() > 1) && (sourceFieldComparerGroup.Operator == LogicalOp.None))
            {
                throw new ArgumentException($"The logical operator may not be {nameof(LogicalOp.None)} when more than one term is specified!");
            }

            foreach (SearchTerm <TItem> sourceSearchTerm in sourceFieldComparerGroup.Terms)
            {
                FieldComparer <TItem> fieldComparer = sourceSearchTerm as FieldComparer <TItem>;
                if (fieldComparer != null)
                {
                    destinationFieldComparerGroup.FieldComparers.Add(new FieldComparer
                    {
                        FieldName    = fieldComparer.FieldName,
                        Operator     = fieldComparer.Operator,
                        CompareValue = fieldComparer.CompareValue
                    });
                }
                else
                {
                    FieldComparerGroup <TItem> sourceSubFieldComparerGroup = sourceSearchTerm as FieldComparerGroup <TItem>;
                    if (sourceSubFieldComparerGroup != null)
                    {
                        var destinationSubFieldComparerGroup = new FieldComparerGroup
                        {
                            Operator = sourceSubFieldComparerGroup.Operator
                        };

                        AppendFieldComparers(sourceSubFieldComparerGroup, destinationSubFieldComparerGroup);

                        if (destinationSubFieldComparerGroup.FieldComparers.Count + destinationSubFieldComparerGroup.FieldComparerGroups.Count > 0)
                        {
                            destinationFieldComparerGroup.FieldComparerGroups.Add(destinationSubFieldComparerGroup);
                        }
                    }
                    else
                    {
                        throw new ArgumentException($"Unknown search term: {sourceSearchTerm?.GetType()}");
                    }
                }
            }
        }