private static IQueryable<DeviceModel> FilterItems(
            IQueryable<DeviceModel> list,
            FilterInfo filter)
        {
            if (list == null)
            {
                throw new ArgumentNullException("list");
            }

            if (filter == null)
            {
                throw new ArgumentNullException("filter");
            }

            if (string.IsNullOrEmpty(filter.ColumnName))
            {
                throw new ArgumentException(
                    "filter.ColumnName is a null reference or empty string.",
                    "filter");
            }

            Func<DeviceProperties, dynamic> getValue = ReflectionHelper.ProducePropertyValueExtractor(
                    filter.ColumnName,
                    false,
                    false);

            Func<DeviceModel, bool> applyFilter = (item) =>
            {
                if (item == null)
                {
                    throw new ArgumentNullException("item");
                }

                if ((filter.FilterType == FilterType.Status) ||
                    string.Equals(
                        filter.ColumnName,
                        "Status",
                        StringComparison.CurrentCultureIgnoreCase))
                {
                    return GetValueMatchesStatus(item, filter.FilterValue);
                }

                if (item.DeviceProperties == null)
                {
                    return false;
                }

                dynamic columnValue = getValue(item.DeviceProperties);
                return GetValueSatisfiesFilter(columnValue, filter);
            };

            return list.Where(applyFilter).AsQueryable();
        }
        public async Task<HttpResponseMessage> GetDevicesAsync(
            [FromUri]string search = null,
            [FromUri]string sortColumn = null,
            [FromUri]QuerySortOrder sortOrder = QuerySortOrder.Ascending,
            [FromUri]int skip = 0,
            [FromUri]int take = 50,
            [FromUri]string[] filterColumn = null,
            [FromUri]FilterType[] filterType = null,
            [FromUri]string[] filterValue = null)
        {
            var filters = new List<FilterInfo>();
            if (filterColumn != null && filterType != null && filterValue != null)
            {
                // valid filters must send ALL three values--ignore unmatched extras
                int validFiltersCount = Math.Min(filterColumn.Length, Math.Min(filterType.Length, filterValue.Length));
                for (int i = 0; i < validFiltersCount; ++i)
                {
                    var f = new FilterInfo()
                    {
                        ColumnName = filterColumn[i],
                        FilterType = filterType[i],
                        FilterValue = filterValue[i]
                    };

                    filters.Add(f);
                }
            }

            var q = new DeviceListQuery()
            {
                SearchQuery = search,
                SortColumn = sortColumn,
                SortOrder = sortOrder,
                Skip = skip,
                Take = take,
                Filters = filters
            };

            return await GetServiceResponseAsync(async () => (await _deviceLogic.GetDevices(q)).Results);
        }
        private static bool GetValueSatisfiesFilter(
            dynamic value,
            FilterInfo filterInfo)
        {
            string strVal;

            if (value == null)
            {
                strVal = string.Empty;
            }
            else
            {
                strVal = value.ToString();
            }

            string match = filterInfo.FilterValue ?? string.Empty;

            switch (filterInfo.FilterType)
            {
                case FilterType.ContainsCaseInsensitive:
                    return strVal.IndexOf(match, StringComparison.CurrentCultureIgnoreCase) >= 0;

                case FilterType.ContainsCaseSensitive:
                    return strVal.IndexOf(match, StringComparison.CurrentCulture) >= 0;

                case FilterType.ExactMatchCaseInsensitive:
                    return string.Equals(strVal, match, StringComparison.CurrentCultureIgnoreCase);

                case FilterType.ExactMatchCaseSensitive:
                    return string.Equals(strVal, match, StringComparison.CurrentCulture);

                case FilterType.StartsWithCaseInsensitive:
                    return strVal.StartsWith(match, StringComparison.CurrentCultureIgnoreCase);

                case FilterType.StartsWithCaseSensitive:
                    return strVal.StartsWith(match, StringComparison.CurrentCulture);
            }

            return false;
        }
        private static IQueryable<dynamic> FilterItems(
            IQueryable<dynamic> list, 
            FilterInfo filter)
        {
            Func<dynamic, bool> applyFilter;
            Func<dynamic, dynamic> getValue;

            if (list == null)
            {
                throw new ArgumentNullException("item");
            }

            if (filter == null)
            {
                throw new ArgumentNullException("filter");
            }

            if (string.IsNullOrEmpty(filter.ColumnName))
            {
                throw new ArgumentException(
                    "filter.ColumnName is a null reference or empty string.",
                    "filter");
            }

            getValue = 
                ReflectionHelper.ProducePropertyValueExtractor(
                    filter.ColumnName, 
                    false, 
                    false);

            applyFilter =
                (item) =>
                {
                    dynamic columnValue;
                    dynamic deviceProperties;

                    if (item == null)
                    {
                        throw new ArgumentNullException("item");
                    }

                    if ((filter.FilterType == FilterType.Status) ||
                        string.Equals(
                            filter.ColumnName,
                            "Status",
                            StringComparison.CurrentCultureIgnoreCase))
                    {
                        return GetValueMatchesStatus(item, filter.FilterValue);
                    }

                    try
                    {
                        deviceProperties = 
                            DeviceSchemaHelper.GetDeviceProperties(item);
                    }
                    catch (DeviceRequiredPropertyNotFoundException)
                    {
                        return false;
                    }

                    columnValue = getValue(deviceProperties);
                    return GetValueSatisfiesFilter(columnValue, filter);
                };

            return list.Where(applyFilter).AsQueryable();
        }