A sort key which can be used to specify the order in which connector objects should be included in the results of a search request.
Since 1.4
            private int Compare(ConnectorObject r1, ConnectorObject r2, ICF.SortKey sortKey)
            {
                IList <object> vs1 = ValuesSorted(r1, sortKey.Field);
                IList <object> vs2 = ValuesSorted(r2, sortKey.Field);

                if (vs1.Count == 0 && vs2.Count == 0)
                {
                    return(0);
                }
                else if (vs1.Count == 0)
                {
                    // Sort resources with missing attributes last.
                    return(1);
                }
                else if (vs2.Count == 0)
                {
                    // Sort resources with missing attributes last.
                    return(-1);
                }
                else
                {
                    object v1 = vs1[0];
                    object v2 = vs2[0];
                    return(sortKey.IsAscendingOrder() ? CompareValues(v1, v2) : -CompareValues(v1, v2));
                }
            }
        public void ExecuteQuery(ObjectClass objectClass, Filter query, ResultsHandler handler, OperationOptions options)
        {
            ICF.SortKey[] sortKeys = options.SortKeys;
            if (null == sortKeys)
            {
                sortKeys = new ICF.SortKey[] { new ICF.SortKey(Name.NAME, true) };
            }

            // Rebuild the full result set.
            SortedSet <ConnectorObject> resultSet = new SortedSet <ConnectorObject>(new ResourceComparator(sortKeys));

            if (null != query)
            {
                foreach (ConnectorObject co in collection.Values)
                {
                    if (query.Accept(co))
                    {
                        resultSet.Add(co);
                    }
                }
            }
            else
            {
                resultSet.UnionWith(collection.Values);
            }
            // Handle the results
            if (null != options.PageSize)
            {
                // Paged Search
                string pagedResultsCookie        = options.PagedResultsCookie;
                string currentPagedResultsCookie = options.PagedResultsCookie;
                int?   pagedResultsOffset        = null != options.PagedResultsOffset ? Math.Max(0, (int)options.PagedResultsOffset) : 0;
                int?   pageSize       = options.PageSize;
                int    index          = 0;
                int    pageStartIndex = null == pagedResultsCookie ? 0 : -1;
                int    handled        = 0;
                foreach (ConnectorObject entry in resultSet)
                {
                    if (pageStartIndex < 0 && pagedResultsCookie.Equals(entry.Name.GetNameValue()))
                    {
                        pageStartIndex = index + 1;
                    }
                    if (pageStartIndex < 0 || index < pageStartIndex)
                    {
                        index++;
                        continue;
                    }
                    if (handled >= pageSize)
                    {
                        break;
                    }
                    if (index >= pagedResultsOffset + pageStartIndex)
                    {
                        if (handler.Handle(entry))
                        {
                            handled++;
                            currentPagedResultsCookie = entry.Name.GetNameValue();
                        }
                        else
                        {
                            break;
                        }
                    }
                    index++;
                }

                if (index == resultSet.Count)
                {
                    currentPagedResultsCookie = null;
                }

                if (handler is SearchResultsHandler)
                {
                    ((SearchResultsHandler)handler).HandleResult(new SearchResult(currentPagedResultsCookie, resultSet.Count - index));
                }
            }
            else
            {
                // Normal Search
                foreach (ConnectorObject entry in resultSet)
                {
                    if (!handler.Handle(entry))
                    {
                        break;
                    }
                }
                if (handler is SearchResultsHandler)
                {
                    ((SearchResultsHandler)handler).HandleResult(new SearchResult());
                }
            }
        }