/// <summary> /// 시퀀스로부터, 조건에 맞는 요소만을 필터링을 수행합니다. /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="sourceCollection"></param> /// <param name="expr"></param> /// <returns></returns> public static IEnumerable <TSource> Where <TSource>(this IndexableCollection <TSource> sourceCollection, Expression <Func <TSource, bool> > expr) { sourceCollection.ShouldNotBeNull("sourceCollection"); expr.ShouldNotBeNull("expr"); var noIndex = true; if (expr.Body.NodeType == ExpressionType.Equal) { // Equality is a binary expression BinaryExpression binaryExpr = (BinaryExpression)expr.Body; // Get aliases for both side Expression leftSide = binaryExpr.Left; Expression rightSide = binaryExpr.Right; var hashRight = GetHashRight(leftSide, rightSide); MemberExpression returnExpr; if (hashRight.HasValue && HasIndexablePropertyOnLeft(leftSide, sourceCollection, out returnExpr)) { // cast to MemberExpression = it allows us to get the property var propertyExpr = returnExpr; var propertyName = propertyExpr.Member.Name; var sourceIndex = sourceCollection.GetIndexByProperty(propertyName); if (sourceIndex.ContainsKey(hashRight.Value)) { var sourceEnum = sourceIndex[hashRight.Value].AsEnumerable(); var results = sourceEnum.Where(expr.Compile()); foreach (var resultItem in results) { yield return(resultItem); } } noIndex = false; } } // 지정된 시퀀스에 인덱스가 없다면... if (noIndex) { if (IsDebugEnabled) { log.Debug("Index가 없으므로 System.Linq.Enumerable.Where()을 수행합니다. "); } var sourceEnum = sourceCollection.AsEnumerable(); var results = sourceEnum.Where(expr.Compile()); foreach (var resultItem in results) { yield return(resultItem); } } }
/// <summary> /// 인덱싱된 시퀀스에서 일치하는 키를 기준으로 두 시퀀스의 요소를 연관시킵니다. 지정한 IEqualityComparer{TKey}를 사용하여 키를 비교합니다. /// </summary> public static IEnumerable <TResult> Join <TOuter, TInner, TKey, TResult>( this IndexableCollection <TOuter> outer, IndexableCollection <TInner> inner, Expression <Func <TOuter, TKey> > outerKeySelector, Expression <Func <TInner, TKey> > innerKeySelector, Func <TOuter, TInner, TResult> resultSelector, IEqualityComparer <TKey> comparer) { outer.ShouldNotBeNull("outer"); inner.ShouldNotBeNull("inner"); outerKeySelector.ShouldNotBeNull("outerKeySelector"); innerKeySelector.ShouldNotBeNull("innerKeySelector"); resultSelector.ShouldNotBeNull("resultSelector"); bool hasIndex = false; if (innerKeySelector.NodeType == ExpressionType.Lambda && innerKeySelector.Body.NodeType == ExpressionType.MemberAccess && outerKeySelector.NodeType == ExpressionType.Lambda && outerKeySelector.Body.NodeType == ExpressionType.MemberAccess) { var memberExpressionInner = (MemberExpression)innerKeySelector.Body; var memberExpressionOuter = (MemberExpression)outerKeySelector.Body; var innerIndex = new MultiMap <int, TInner>(); var outerIndex = new MultiMap <int, TOuter>(); if (inner.PropertyHasIndex(memberExpressionInner.Member.Name) && outer.PropertyHasIndex(memberExpressionOuter.Member.Name)) { innerIndex = inner.GetIndexByProperty(memberExpressionInner.Member.Name); outerIndex = outer.GetIndexByProperty(memberExpressionOuter.Member.Name); hasIndex = true; } if (hasIndex) { foreach (int outerKey in outerIndex.Keys) { IList <TOuter> outerGroup = outerIndex[outerKey]; IList <TInner> innerGroup; if (innerIndex.TryGetValue(outerKey, out innerGroup)) { // join on the GROUPS based on key result IEnumerable <TInner> inners = innerGroup.AsEnumerable(); IEnumerable <TOuter> outers = outerGroup.AsEnumerable(); IEnumerable <TResult> results = outers.Join(inners, outerKeySelector.Compile(), innerKeySelector.Compile(), resultSelector, comparer); foreach (TResult resultItem in results) { yield return(resultItem); } } } } } if (hasIndex == false) { if (IsDebugEnabled) { log.Debug("Index가 없으므로 System.Linq.Enumerable.Join()을 수행합니다. "); } var inners = inner.AsEnumerable(); var outers = outer.AsEnumerable(); var results = outers.Join(inners, outerKeySelector.Compile(), innerKeySelector.Compile(), resultSelector, comparer); foreach (var resultItem in results) { yield return(resultItem); } } }