//extend the where when we are working with indexable collections! public static IEnumerable <T> Where <T> ( this XbimIndexedCollection <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) MemberExpression returnedEx = GetIndexablePropertyOnLeft(leftSide, sourceCollection); if (hashRight.HasValue && returnedEx != null) { //cast to MemberExpression - it allows us to get the property MemberExpression propExp = returnedEx; string property = propExp.Member.Name; IEnumerable <T> values = sourceCollection.GetValues(property, hashRight.Value); if (values != null) { foreach (T item in values) { 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(); IEnumerable <T> result = sourceEnum.Where(expr.Compile()); foreach (T resultItem in result) { yield return(resultItem); } } }
private static MemberExpression GetIndexablePropertyOnLeft <T>(Expression leftSide, XbimIndexedCollection <T> sourceCollection) { MemberExpression mex = leftSide as MemberExpression; if (leftSide.NodeType == ExpressionType.Call) { MethodCallExpression call = leftSide as MethodCallExpression; if (call.Method.Name == "CompareString") { mex = call.Arguments[0] as MemberExpression; } } return(mex); }