public IQueryable CreateQuery(Expression expression) { //handles OfType call Type elementType = TypeSystem.GetElementType(expression.Type); if (expression is MethodCallExpression) { MethodCallExpression mex = (MethodCallExpression)expression; if (mex.Method.Name == "OfType" || mex.Method.Name == "Cast") { Type listType = typeof(Enumerable); List <C> listFrom = _parent.ToList <C>(); List <object> paramList = new List <object>(); paramList.Add(listFrom); foreach (MethodInfo method in listType.GetMethods()) { if (method.Name == mex.Method.Name) { Type[] genericArguments = { mex.Method.GetGenericArguments().First() }; MethodInfo genericMethodInfo = method.MakeGenericMethod(genericArguments); System.Collections.IEnumerable thingWeGotBack = (System.Collections.IEnumerable)genericMethodInfo.Invoke(null, paramList.ToArray()); return(thingWeGotBack.AsQueryable()); } } } } _filter = new LinqBindingList <C>(_parent, this, expression); return(_filter); }
public IQueryable <TElement> CreateQuery <TElement>(Expression expression) { Type elementType = TypeSystem.GetElementType(expression.Type); try { MethodCallExpression mex = (MethodCallExpression)expression; if (typeof(TElement) == typeof(C) && mex.Method.Name == "Where" && _filter == null) { _filter = new LinqBindingList <C>(_parent, this, expression); _filter.BuildFilterIndex(); return((IQueryable <TElement>)_filter); } else { //handle non identity projections here switch (mex.Method.Name) { case "Select": UnaryExpression selectHolder = (UnaryExpression)mex.Arguments[1]; LambdaExpression theSelect = (LambdaExpression)selectHolder.Operand; Expression <Func <C, TElement> > selectorLambda = Expression.Lambda <Func <C, TElement> >(theSelect.Body, theSelect.Parameters); Func <C, TElement> selector = selectorLambda.Compile(); if (_filter == null) { return(_parent.Select <C, TElement>(selector).AsQueryable <TElement>()); } else { return(_filter.Select <C, TElement>(selector).AsQueryable <TElement>()); } case "Concat": return( System.Linq.Queryable.Concat <TElement>( //at this point, no more filtering, just move it to a concatenated list of items, which we turn to queryable so that the method considers it ok ((IQueryable <TElement>)_filter).ToList <TElement>().AsQueryable <TElement>(), //have to eval on the method to make it not a ParameterExpression, but the actual Enumerable inside (IEnumerable <TElement>)Eval(mex.Arguments[1])) ); case "Where": default: List <C> listFrom; if (_filter == null) { listFrom = _parent.ToList <C>(); } else { listFrom = _filter.ToList <C>(); } Type listType = typeof(Enumerable); MethodInfo[] listMethods = listType.GetMethods(); List <object> paramList = new List <object>(); paramList.Add(listFrom); int i = 0; foreach (object arg in mex.Arguments) { if (i > 0) { if (arg is Expression) { paramList.Add(Compile((Expression)arg)); } else { paramList.Add(arg); } } i++; } foreach (MethodInfo method in listMethods) { if (MethodsEquivalent(mex, method)) { Type[] genericArguments = mex.Method.GetGenericArguments(); MethodInfo genericMethodInfo = method.MakeGenericMethod(genericArguments); var testObject = genericMethodInfo.Invoke(null, paramList.ToArray()); IQueryable <TElement> testObjectQ = ((IEnumerable <TElement>)testObject).AsQueryable <TElement>(); return(testObjectQ); } } return(null); } } } catch (System.Reflection.TargetInvocationException tie) { throw tie.InnerException; } }