public IQueryable <TElement> CreateQuery <TElement>(Expression expression) { if (!(expression is MethodCallExpression mc)) { throw new ArgumentException("Invalid expression", nameof(expression)); } var queryable = ConstantFinder <IQueryable <TSource> > .FindIn(mc.Arguments[0]); if (queryable == null) { throw new InvalidOperationException("Cannot find source."); } if (mc.Method.TryFindMethod(out var method)) { var arguments = mc.Arguments.Select(x => LambdaFinder.FindIn(x) ?? ConstantFinder <object> .FindIn(x)).ToArray(); return((IQueryable <TElement>)method.Invoke(null, arguments)); } var source = new Lazy <IEnumerable <TSource> >(() => (queryable as IQueryableCollection <TSource>)?.Source ?? queryable); var collection = new Lazy <IReadOnlyObservableCollection <TSource> >(() => source.Value as IReadOnlyObservableCollection <TSource>); var list = new Lazy <IReadOnlyObservableList <TSource> >(() => source.Value as IReadOnlyObservableList <TSource>); switch (mc.Method.Name) { case "OfType" when mc.Arguments.Count == 1 && collection.Value != null: return(list.Value != null ? new CastingReadOnlyObservableList <TSource, TElement>(list.Value.ListWhere(x => x is TElement)).AsQueryableCollection() : new CastingReadOnlyObservableCollection <TSource, TElement>(source.Value.ListWhere(x => x is TElement)).AsQueryableCollection()); case "Cast" when mc.Arguments.Count == 1 && collection.Value != null: return(list.Value != null ? new CastingReadOnlyObservableList <TSource, TElement>(list.Value).AsQueryableCollection() : new CastingReadOnlyObservableCollection <TSource, TElement>(collection.Value).AsQueryableCollection()); } var updater = new QueryModifier(); expression = updater.Visit(expression); if (updater.Source == null) { throw new InvalidOperationException(); } var result = updater.Source.Provider.CreateQuery <TElement>(expression); return(result); }
public TResult Execute <TResult>(Expression expression) { if (expression is MethodCallExpression mc) { if (mc.Method.TryFindMethod(out var method)) { var arguments = mc.Arguments.Select(x => LambdaFinder.FindIn(x) ?? ConstantFinder <object> .FindIn(x)).ToArray(); return((TResult)method.Invoke(null, arguments)); } } var updater = new QueryModifier(); expression = updater.Visit(expression); if (updater.Source == null) { throw new InvalidOperationException(); } var result = updater.Source.Provider.Execute <TResult>(expression); return(result); }