private static bool HasIndexablePropertyOnLeft <TSource>(Expression leftSide, IndexableCollection <TSource> sourceCollection, out MemberExpression memberExpr) { memberExpr = null; var mex = leftSide as MemberExpression; if (leftSide.NodeType == ExpressionType.Call) { var call = leftSide as MethodCallExpression; if (call != null) { if (call.Method.Name.EqualTo("CompareString")) { mex = call.Arguments[0] as MemberExpression; } } } if (mex == null) { return(false); } memberExpr = mex; return(sourceCollection.PropertyHasIndex(mex.Member.Name)); }
/// <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); } } }