/// <summary>Enumerates create enumerable in this collection.</summary> /// <exception cref="Exception">Thrown when an exception error condition occurs.</exception> /// <returns> /// An enumerator that allows foreach to be used to process create enumerable in this collection. /// </returns> public IEnumerable <T> CreateEnumerable() { if (Childs.Count == 0) { return(OriginalQueryable); } IQueryable newQuery = null; var createAnonymousFromQueryMethod = GetType().GetMethod("CreateAnonymousFromQuery"); foreach (var child in Childs) { var childQuery = child.CreateIncludeQuery(OriginalQueryable); if (newQuery == null) { newQuery = OriginalQueryable.Select(x => new { x, child = childQuery }); } else { // REFLECTION: newQuery.CreateAnonymousFromQuery<TElement>(newQuery, childQuery); var createAnonymousFromQueryMethodGeneric = createAnonymousFromQueryMethod.MakeGenericMethod(newQuery.ElementType); newQuery = (IQueryable)createAnonymousFromQueryMethodGeneric.Invoke(this, new object[] { newQuery, childQuery }); } } // REFLECTION: newQuery.ToList(); var toListMethod = typeof(Enumerable).GetMethod("ToList").MakeGenericMethod(newQuery.ElementType); var toList = (IEnumerable <object>)toListMethod.Invoke(null, new object[] { newQuery }); try { // TODO: Optimize this code while (true) { toList = toList.Select(x => ((dynamic)x).x).ToList(); if (!toList.Any()) { return(new List <T>()); } } } catch (Exception) { } var list = toList.Cast <T>().ToList(); #if EF6 // FIX lazy loading QueryIncludeFilterLazyLoading.SetLazyLoaded(list, Childs); #endif // FIX null collection QueryIncludeFilterNullCollection.NullCollectionToEmpty(list, Childs); return(list); }
/// <summary>Executes the given expression.</summary> /// <exception cref="Exception">Thrown when an exception error condition occurs.</exception> /// <typeparam name="TResult">Type of the result.</typeparam> /// <param name="expression">The expression to execute.</param> /// <returns>The object returned by the execution of the expression.</returns> public TResult Execute <TResult>(Expression expression) { var methodCall = expression as MethodCallExpression; if (methodCall == null) { throw new Exception(ExceptionMessage.GeneralException); } if (methodCall.Method.Name == "All" || methodCall.Method.Name == "Any" || methodCall.Method.Name == "Average" || methodCall.Method.Name == "Contains" || methodCall.Method.Name == "Count" || methodCall.Method.Name == "LongCount" || methodCall.Method.Name == "Max" || methodCall.Method.Name == "Min" || methodCall.Method.Name == "SequenceEqual" || methodCall.Method.Name == "Sum") { return(OriginalProvider.Execute <TResult>(expression)); } var currentQuery = CurrentQueryable; var currentMethod = methodCall.Method.GetGenericMethodDefinition(); // CHECK if the internal expression can be supported var isExpressionSupported = false; var firstExpression = methodCall.Arguments.FirstOrDefault(x => x.Type.IsSubclassOf(typeof(Expression))); var unaryExpression = firstExpression as UnaryExpression; if (firstExpression != null && unaryExpression != null && methodCall.Arguments.Count == 2) { var lambdaExpression = unaryExpression.Operand as LambdaExpression; if (lambdaExpression != null) { if (lambdaExpression.Type == typeof(Func <,>).MakeGenericType(currentQuery.ElementType, typeof(bool))) { var method = typeof(Queryable).GetMethods().First(x => x.Name == "Where" && x.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Length == 2); var methodGeneric = method.MakeGenericMethod(currentQuery.ElementType); currentQuery = (QueryIncludeFilterParentQueryable <T>)methodGeneric.Invoke(null, new object[] { currentQuery, lambdaExpression }); currentMethod = typeof(Queryable).GetMethods().FirstOrDefault(x => x.Name == currentMethod.Name && x.GetParameters().Length == 1); isExpressionSupported = currentMethod != null; } } } if (firstExpression != null && !isExpressionSupported) { throw new Exception(ExceptionMessage.QueryIncludeFilter_ArgumentExpression); } // CREATE the new query by selecting included entities in an anonymous type var newQuery = currentQuery.CreateQueryable(); // CREATE a new immediate method from the immediate method used by the user var newImmediateMethod = currentMethod.MakeGenericMethod(newQuery.ElementType); // REPLACE the first argument with the new query expression var arguments = methodCall.Arguments.ToList(); arguments[0] = newQuery.Expression; // REMOVE the last argument if a "Predicate" method was previously used if (firstExpression != null) { arguments.RemoveAt(1); } // CREATE the new expression var newExpression = Expression.Call(null, newImmediateMethod, arguments); // EXECUTE the new expression var value = OriginalProvider.Execute(newExpression); // CHECK if a value has been returned if (value == null) { return((TResult)(object)null); } // GET the query result from the anonymous type var result = value; PropertyInfo property; while ((property = result.GetType().GetProperty("x")) != null) { result = property.GetValue(result, null); } #if EF6 // FIX lazy loading QueryIncludeFilterLazyLoading.SetLazyLoaded(result, currentQuery.Childs); #endif // FIX null collection QueryIncludeFilterNullCollection.NullCollectionToEmpty(result, currentQuery.Childs); return((TResult)result); }