Exemple #1
0
 public static IEnumerable <TResult> Join <T, TInner, TKey, TResult>(
     this IndexableCollection <T> outer,
     IndexableCollection <TInner> inner,
     Expression <Func <T, TKey> > outerKeySelector,
     Expression <Func <TInner, TKey> > innerKeySelector,
     Func <T, TInner, TResult> resultSelector)
 {
     return(outer.Join <T, TInner, TKey, TResult>(inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer <TKey> .Default));
 }
Exemple #2
0
 private static bool HasIndexablePropertyOnLeft <T>(Expression leftSide, IndexableCollection <T> sourceCollection)
 {
     if (leftSide.NodeType == ExpressionType.MemberAccess)
     {
         return(sourceCollection.PropertyHasIndex(((MemberExpression)leftSide).Member.Name));
     }
     else
     {
         return(false);
     }
 }
Exemple #3
0
        //extend the where when we are working with indexable collections!
        public static IEnumerable <T> Where <T>
        (
            this IndexableCollection <T> sourceCollection,
            Expression <Func <T, bool> > expr
        )
        {
            //our indexes work from the hash values of that which is indexed, regardless of type
            int? hashRight = null;
            bool noIndex   = true;

            //indexes only work on equality expressions here
            if (expr.Body.NodeType == ExpressionType.Equal)
            {
                //Equality is a binary expression
                BinaryExpression binExp = (BinaryExpression)expr.Body;
                //Get some aliases for either side
                Expression leftSide  = binExp.Left;
                Expression rightSide = binExp.Right;

                hashRight = GetHashRight(leftSide, rightSide);

                //if we were able to create a hash from the right side (likely)
                if (hashRight.HasValue && HasIndexablePropertyOnLeft <T>(leftSide, sourceCollection))
                {
                    //cast to MemberExpression - it allows us to get the property
                    MemberExpression            propExp  = (MemberExpression)leftSide;
                    string                      property = propExp.Member.Name;
                    Dictionary <int, List <T> > myIndex  =
                        sourceCollection.GetIndexByProperty(property);
                    if (myIndex.ContainsKey(hashRight.Value))
                    {
                        IEnumerable <T> sourceEnum = myIndex[hashRight.Value].AsEnumerable <T>();
                        IEnumerable <T> result     = sourceEnum.Where <T>(expr.Compile());
                        foreach (T item in result)
                        {
                            yield return(item);
                        }
                    }
                    noIndex = false; //we found an index, whether it had values or not is another matter
                }
            }
            if (noIndex) //no index?  just do it the normal slow way then...
            {
                IEnumerable <T> sourceEnum = sourceCollection.AsEnumerable <T>();
                IEnumerable <T> result     = sourceEnum.Where <T>(expr.Compile());
                foreach (T resultItem in result)
                {
                    yield return(resultItem);
                }
            }
        }
Exemple #4
0
        public static IEnumerable <TResult> Join <T, TInner, TKey, TResult>(
            this IndexableCollection <T> outer,
            IndexableCollection <TInner> inner,
            Expression <Func <T, TKey> > outerKeySelector,
            Expression <Func <TInner, TKey> > innerKeySelector,
            Func <T, TInner, TResult> resultSelector,
            IEqualityComparer <TKey> comparer)
        {
            if (outer == null || inner == null || outerKeySelector == null || innerKeySelector == null || resultSelector == null)
            {
                throw new ArgumentNullException();
            }

            bool haveIndex = false;

            if (innerKeySelector.NodeType == ExpressionType.Lambda &&
                innerKeySelector.Body.NodeType == ExpressionType.MemberAccess &&
                outerKeySelector.NodeType == ExpressionType.Lambda &&
                outerKeySelector.Body.NodeType == ExpressionType.MemberAccess)
            {
                MemberExpression membExpInner = (MemberExpression)innerKeySelector.Body;
                MemberExpression membExpOuter = (MemberExpression)outerKeySelector.Body;
                Dictionary <int, List <TInner> > innerIndex = new Dictionary <int, List <TInner> >();
                Dictionary <int, List <T> >      outerIndex = new Dictionary <int, List <T> >();

                if (inner.PropertyHasIndex(membExpInner.Member.Name) &&
                    outer.PropertyHasIndex(membExpOuter.Member.Name))
                {
                    innerIndex = inner.GetIndexByProperty(membExpInner.Member.Name);
                    outerIndex = outer.GetIndexByProperty(membExpOuter.Member.Name);
                    haveIndex  = true;
                }

                if (haveIndex)
                {
                    foreach (int outerKey in outerIndex.Keys)
                    {
                        List <T>      outerGroup = outerIndex[outerKey];
                        List <TInner> innerGroup;
                        if (innerIndex.TryGetValue(outerKey, out innerGroup))
                        {
                            //do a join on the GROUPS based on key result
                            IEnumerable <TInner>  innerEnum = innerGroup.AsEnumerable <TInner>();
                            IEnumerable <T>       outerEnum = outerGroup.AsEnumerable <T>();
                            IEnumerable <TResult> result    = outerEnum.Join <T, TInner, TKey, TResult>(innerEnum, outerKeySelector.Compile(), innerKeySelector.Compile(), resultSelector, comparer);
                            foreach (TResult resultItem in result)
                            {
                                yield return(resultItem);
                            }
                        }
                    }
                }
            }
            if (!haveIndex)
            {
                //this will happen if we don't have keys in the right places
                IEnumerable <TInner>  innerEnum = inner.AsEnumerable <TInner>();
                IEnumerable <T>       outerEnum = outer.AsEnumerable <T>();
                IEnumerable <TResult> result    = outerEnum.Join <T, TInner, TKey, TResult>(innerEnum, outerKeySelector.Compile(), innerKeySelector.Compile(), resultSelector, comparer);
                foreach (TResult resultItem in result)
                {
                    yield return(resultItem);
                }
            }
        }