internal SingleFilterInfo ParseFilter(string filterPart)
        {
            filterPart = filterPart.Replace("==", "=");
            var filterInfo = new SingleFilterInfo
            {
                OperatorValue = DetermineFilterOperator(filterPart)
            };

            var filterStringParts = filterPart.Split((char)filterInfo.OperatorValue);

            filterInfo.PropName =
                filterStringParts[0].Replace("[", "").
                Replace("]", "").Replace(" AND ", "").Trim();

            // Get the property descriptor for the filter property name.
            var filterPropDesc = TypeDescriptor.GetProperties(typeof(T))[filterInfo.PropName];

            // Convert the filter compare value to the property type.
            if (filterPropDesc == null)
            {
                throw new InvalidOperationException("Specified property to " +
                                                    "filter " + filterInfo.PropName +
                                                    " on does not exist on type: " + typeof(T).Name);
            }

            filterInfo.PropDesc = filterPropDesc;

            var comparePartNoQuotes = StripOffQuotes(filterStringParts[1]);

            try
            {
                var converter = TypeDescriptor.GetConverter(filterPropDesc.PropertyType);
                filterInfo.CompareValue =
                    converter.ConvertFromString(comparePartNoQuotes);
            }
            catch (NotSupportedException)
            {
                throw new InvalidOperationException("Specified filter" +
                                                    "value " + comparePartNoQuotes + " can not be converted" +
                                                    "from string. Implement a type converter for " +
                                                    filterPropDesc.PropertyType);
            }
            return(filterInfo);
        }
        internal void ApplyFilter(SingleFilterInfo filterParts, bool addMatches = true)
        {
            // Check to see if the property type we are filtering by implements
            // the IComparable interface.
            var interfaceType =
                TypeDescriptor.GetProperties(typeof(T))[filterParts.PropName]
                .PropertyType.GetInterface("IComparable");

            if (interfaceType == null)
            {
                throw new InvalidOperationException(
                          "Filtered property must implement IComparable.");
            }

            var removes = new List <T>();

            // Check each value and add to the results list.
            if (addMatches)
            {
                foreach (var item in originalList.Where(i => !Contains(i)))
                {
                    if (filterParts.PropDesc.GetValue(item) == null || Contains(item))
                    {
                        continue;
                    }
                    var compareValue = filterParts.PropDesc.GetValue(item) as IComparable;
                    var result       = compareValue.CompareTo(filterParts.CompareValue);

                    if (filterParts.OperatorValue == EQ && result == 0)
                    {
                        Add(item);
                    }
                    if (filterParts.OperatorValue == GT && result > 0)
                    {
                        Add(item);
                    }
                    if (filterParts.OperatorValue == LT && result < 0)
                    {
                        Add(item);
                    }
                }
            }
            else // removing items that don't match
            {
                foreach (var item in this)
                {
                    if (filterParts.PropDesc.GetValue(item) == null || !Contains(item))
                    {
                        continue;
                    }
                    var compareValue = filterParts.PropDesc.GetValue(item) as IComparable;
                    var result       = compareValue.CompareTo(filterParts.CompareValue);
                    if (filterParts.OperatorValue == EQ && result != 0)
                    {
                        removes.Add(item);
                    }
                    if (filterParts.OperatorValue == GT && result <= 0)
                    {
                        removes.Add(item);
                    }
                    if (filterParts.OperatorValue == LT && result >= 0)
                    {
                        removes.Add(item);
                    }
                }
            }
            foreach (var item in removes)
            {
                Remove(item);
            }
        }