Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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;
            }
        }