private Expression RewritePropertyAccess(
            Expression expression,
            IReadOnlyList <IPropertyBase> properties,
            IQuerySource querySource)
        {
            if (querySource != null &&
                properties.Count > 0 &&
                properties.All(p => p is INavigation) &&
                properties[properties.Count - 1] is INavigation lastNavigation &&
                lastNavigation.IsCollection())
            {
                var qsre = new QuerySourceReferenceExpression(querySource);

                CollectionNavigationIncludeResultOperators.Add(
                    new IncludeResultOperator(properties.Cast <INavigation>().ToArray(), qsre));

                var parameter       = Expression.Parameter(querySource.ItemType, querySource.ItemName);
                var accessorBody    = BuildCollectionAccessorExpression(parameter, properties);
                var emptyCollection = lastNavigation.GetCollectionAccessor().Create();

                return(Expression.Call(
                           ProjectCollectionNavigationMethodInfo
                           .MakeGenericMethod(querySource.ItemType, expression.Type),
                           qsre,
                           Expression.Lambda(
                               Expression.Coalesce(
                                   accessorBody,
                                   Expression.Constant(emptyCollection, accessorBody.Type)),
                               parameter)));
            }

            return(expression);
        }
コード例 #2
0
        private Expression RewritePropertyAccess(
            Expression expression,
            IReadOnlyList <IPropertyBase> properties,
            IQuerySource querySource)
        {
            if (querySource != null &&
                properties.Count > 0 &&
                properties.All(p => p is INavigation) &&
                properties[properties.Count - 1] is INavigation lastNavigation &&
                lastNavigation.IsCollection())
            {
                // include doesn't handle navigations on derived class, so we can't leverage include pipeline for those cases
                var expectedCallerType = querySource.ItemType;
                foreach (var property in properties)
                {
                    if (expectedCallerType != property.DeclaringType.ClrType)
                    {
                        return(expression);
                    }

                    expectedCallerType = property.ClrType;
                }

                var qsre = new QuerySourceReferenceExpression(querySource);

                CollectionNavigationIncludeResultOperators.Add(
                    new IncludeResultOperator(properties.Cast <INavigation>().ToArray(), qsre));

                var parameter       = Expression.Parameter(querySource.ItemType, querySource.ItemName);
                var accessorBody    = BuildCollectionAccessorExpression(parameter, properties);
                var emptyCollection = lastNavigation.GetCollectionAccessor().Create();

                return(Expression.Call(
                           ProjectCollectionNavigationMethodInfo
                           .MakeGenericMethod(querySource.ItemType, expression.Type),
                           qsre,
                           Expression.Lambda(
                               Expression.Coalesce(
                                   accessorBody,
                                   Expression.Constant(emptyCollection, accessorBody.Type)),
                               parameter)));
            }

            return(expression);
        }