private Expression CreateLambdaBodyInitializer(IDictionary <ResourceFieldAttribute, QueryLayer> selectors, ResourceContext resourceContext, LambdaScope lambdaScope, bool lambdaAccessorRequiresTestForNull) { var propertySelectors = ToPropertySelectors(selectors, resourceContext, lambdaScope.Parameter.Type); MemberBinding[] propertyAssignments = propertySelectors.Select(selector => CreatePropertyAssignment(selector, lambdaScope)).Cast <MemberBinding>().ToArray(); NewExpression newExpression = _resourceFactory.CreateNewExpression(lambdaScope.Accessor.Type); Expression memberInit = Expression.MemberInit(newExpression, propertyAssignments); if (lambdaScope.HasManyThrough != null) { MemberBinding outerPropertyAssignment = Expression.Bind(lambdaScope.HasManyThrough.RightProperty, memberInit); NewExpression outerNewExpression = _resourceFactory.CreateNewExpression(lambdaScope.HasManyThrough.ThroughType); memberInit = Expression.MemberInit(outerNewExpression, outerPropertyAssignment); } if (!lambdaAccessorRequiresTestForNull) { return(memberInit); } return(TestForNull(lambdaScope.Accessor, memberInit)); }
public override Expression VisitCollectionNotEmpty(CollectionNotEmptyExpression expression, Type argument) { Expression property = Visit(expression.TargetCollection, argument); Type elementType = CollectionConverter.TryGetCollectionElementType(property.Type); if (elementType == null) { throw new InvalidOperationException("Expression must be a collection."); } Expression predicate = null; if (expression.Filter != null) { var hasManyThrough = expression.TargetCollection.Fields.Last() as HasManyThroughAttribute; var lambdaScopeFactory = new LambdaScopeFactory(_nameFactory, hasManyThrough); using LambdaScope lambdaScope = lambdaScopeFactory.CreateScope(elementType); var builder = new WhereClauseBuilder(property, lambdaScope, typeof(Enumerable), _nameFactory); predicate = builder.GetPredicateLambda(expression.Filter); } return(AnyExtensionMethodCall(elementType, property, predicate)); }
private Expression CreateCollectionInitializer(LambdaScope lambdaScope, PropertyInfo collectionProperty, Type elementType, QueryLayer layer, LambdaScopeFactory lambdaScopeFactory) { MemberExpression propertyExpression = Expression.Property(lambdaScope.Accessor, collectionProperty); var builder = new QueryableBuilder(propertyExpression, elementType, typeof(Enumerable), _nameFactory, _resourceFactory, _resourceContextProvider, _entityModel, lambdaScopeFactory); Expression layerExpression = builder.ApplyQuery(layer); Type enumerableOfElementType = typeof(IEnumerable <>).MakeGenericType(elementType); Type typedCollection = TypeHelper.ToConcreteCollectionType(collectionProperty.PropertyType); ConstructorInfo typedCollectionConstructor = typedCollection.GetConstructor(new[] { enumerableOfElementType }); if (typedCollectionConstructor == null) { throw new Exception( $"Constructor on '{typedCollection.Name}' that accepts '{enumerableOfElementType.Name}' not found."); } return(Expression.New(typedCollectionConstructor, layerExpression)); }
private Expression CreateCollectionInitializer(LambdaScope lambdaScope, PropertyInfo collectionProperty, Type elementType, QueryLayer layer, LambdaScopeFactory lambdaScopeFactory) { MemberExpression propertyExpression = Expression.Property(lambdaScope.Accessor, collectionProperty); var builder = new QueryableBuilder(propertyExpression, elementType, typeof(Enumerable), _nameFactory, _resourceFactory, _resourceContextProvider, _entityModel, lambdaScopeFactory); Expression layerExpression = builder.ApplyQuery(layer); // Earlier versions of EF Core 3.x failed to understand `query.ToHashSet()`, so we emit `new HashSet(query)` instead. // Interestingly, EF Core 5 RC1 fails to understand `new HashSet(query)`, so we emit `query.ToHashSet()` instead. // https://github.com/dotnet/efcore/issues/22902 if (EntityFrameworkCoreSupport.Version.Major < 5) { Type enumerableOfElementType = typeof(IEnumerable <>).MakeGenericType(elementType); Type typedCollection = CollectionConverter.ToConcreteCollectionType(collectionProperty.PropertyType); ConstructorInfo typedCollectionConstructor = typedCollection.GetConstructor(enumerableOfElementType.AsArray()); if (typedCollectionConstructor == null) { throw new InvalidOperationException($"Constructor on '{typedCollection.Name}' that accepts '{enumerableOfElementType.Name}' not found."); } return(Expression.New(typedCollectionConstructor, layerExpression)); } string operationName = CollectionConverter.TypeCanContainHashSet(collectionProperty.PropertyType) ? "ToHashSet" : "ToList"; return(CopyCollectionExtensionMethodCall(layerExpression, operationName, elementType)); }
public IncludeClauseBuilder(Expression source, LambdaScope lambdaScope, ResourceContext resourceContext, IResourceContextProvider resourceContextProvider) : base(lambdaScope) { _source = source ?? throw new ArgumentNullException(nameof(source)); _resourceContext = resourceContext ?? throw new ArgumentNullException(nameof(resourceContext)); _resourceContextProvider = resourceContextProvider ?? throw new ArgumentNullException(nameof(resourceContextProvider)); }
protected virtual Expression ApplyFilter(Expression source, FilterExpression filter) { using LambdaScope lambdaScope = _lambdaScopeFactory.CreateScope(_elementType); var builder = new WhereClauseBuilder(source, lambdaScope, _extensionType, _nameFactory); return(builder.ApplyWhere(filter)); }
protected virtual Expression ApplyInclude(Expression source, IncludeExpression include, ResourceContext resourceContext) { using LambdaScope lambdaScope = _lambdaScopeFactory.CreateScope(_elementType); var builder = new IncludeClauseBuilder(source, lambdaScope, resourceContext, _resourceContextProvider); return(builder.ApplyInclude(include)); }
protected virtual Expression ApplyPagination(Expression source, PaginationExpression pagination) { using LambdaScope lambdaScope = _lambdaScopeFactory.CreateScope(_elementType); var builder = new SkipTakeClauseBuilder(source, lambdaScope, _extensionType); return(builder.ApplySkipTake(pagination)); }
protected virtual Expression ApplySort(Expression source, SortExpression sort) { using LambdaScope lambdaScope = _lambdaScopeFactory.CreateScope(_elementType); var builder = new OrderClauseBuilder(source, lambdaScope, _extensionType); return(builder.ApplyOrderBy(sort)); }
public WhereClauseBuilder(Expression source, LambdaScope lambdaScope, Type extensionType) : base(lambdaScope) { ArgumentGuard.NotNull(source, nameof(source)); ArgumentGuard.NotNull(extensionType, nameof(extensionType)); _source = source; _extensionType = extensionType; }
protected virtual Expression ApplyProjection(Expression source, IDictionary <ResourceFieldAttribute, QueryLayer> projection, ResourceContext resourceContext) { using LambdaScope lambdaScope = _lambdaScopeFactory.CreateScope(_elementType); var builder = new SelectClauseBuilder(source, lambdaScope, _entityModel, _extensionType, _nameFactory, _resourceFactory, _resourceContextProvider); return(builder.ApplySelect(projection, resourceContext)); }
public SelectClauseBuilder(Expression source, LambdaScope lambdaScope, IModel entityModel, Type extensionType, LambdaParameterNameFactory nameFactory, IResourceFactory resourceFactory, IResourceContextProvider resourceContextProvider) : base(lambdaScope) { _source = source ?? throw new ArgumentNullException(nameof(source)); _entityModel = entityModel ?? throw new ArgumentNullException(nameof(entityModel)); _extensionType = extensionType ?? throw new ArgumentNullException(nameof(extensionType)); _nameFactory = nameFactory ?? throw new ArgumentNullException(nameof(nameFactory)); _resourceFactory = resourceFactory ?? throw new ArgumentNullException(nameof(resourceFactory)); _resourceContextProvider = resourceContextProvider ?? throw new ArgumentNullException(nameof(resourceContextProvider)); }
public WhereClauseBuilder(Expression source, LambdaScope lambdaScope, Type extensionType, LambdaParameterNameFactory nameFactory) : base(lambdaScope) { ArgumentGuard.NotNull(source, nameof(source)); ArgumentGuard.NotNull(extensionType, nameof(extensionType)); ArgumentGuard.NotNull(nameFactory, nameof(nameFactory)); _source = source; _extensionType = extensionType; _nameFactory = nameFactory; }
public IncludeClauseBuilder(Expression source, LambdaScope lambdaScope, ResourceContext resourceContext, IResourceContextProvider resourceContextProvider) : base(lambdaScope) { ArgumentGuard.NotNull(source, nameof(source)); ArgumentGuard.NotNull(resourceContext, nameof(resourceContext)); ArgumentGuard.NotNull(resourceContextProvider, nameof(resourceContextProvider)); _source = source; _resourceContext = resourceContext; _resourceContextProvider = resourceContextProvider; }
private MemberAssignment CreatePropertyAssignment(PropertySelector selector, LambdaScope lambdaScope) { MemberExpression propertyAccess = Expression.Property(lambdaScope.Accessor, selector.Property); Expression assignmentRightHandSide = propertyAccess; if (selector.NextLayer != null) { HasManyThroughAttribute hasManyThrough = selector.OriginatingField as HasManyThroughAttribute; var lambdaScopeFactory = new LambdaScopeFactory(_nameFactory, hasManyThrough); assignmentRightHandSide = CreateAssignmentRightHandSideForLayer(selector.NextLayer, lambdaScope, propertyAccess, selector.Property, lambdaScopeFactory); } return(Expression.Bind(selector.Property, assignmentRightHandSide)); }
public SelectClauseBuilder(Expression source, LambdaScope lambdaScope, IModel entityModel, Type extensionType, LambdaParameterNameFactory nameFactory, IResourceFactory resourceFactory, IResourceContextProvider resourceContextProvider) : base(lambdaScope) { ArgumentGuard.NotNull(source, nameof(source)); ArgumentGuard.NotNull(entityModel, nameof(entityModel)); ArgumentGuard.NotNull(extensionType, nameof(extensionType)); ArgumentGuard.NotNull(nameFactory, nameof(nameFactory)); ArgumentGuard.NotNull(resourceFactory, nameof(resourceFactory)); ArgumentGuard.NotNull(resourceContextProvider, nameof(resourceContextProvider)); _source = source; _entityModel = entityModel; _extensionType = extensionType; _nameFactory = nameFactory; _resourceFactory = resourceFactory; _resourceContextProvider = resourceContextProvider; }
private Expression CreateAssignmentRightHandSideForLayer(QueryLayer layer, LambdaScope outerLambdaScope, MemberExpression propertyAccess, PropertyInfo selectorPropertyInfo, LambdaScopeFactory lambdaScopeFactory) { Type collectionElementType = TypeHelper.TryGetCollectionElementType(selectorPropertyInfo.PropertyType); Type bodyElementType = collectionElementType ?? selectorPropertyInfo.PropertyType; if (collectionElementType != null) { return(CreateCollectionInitializer(outerLambdaScope, selectorPropertyInfo, bodyElementType, layer, lambdaScopeFactory)); } if (layer.Projection == null || !layer.Projection.Any()) { return(propertyAccess); } using var scope = lambdaScopeFactory.CreateScope(bodyElementType, propertyAccess); return(CreateLambdaBodyInitializer(layer.Projection, layer.ResourceContext, scope, true)); }
protected QueryClauseBuilder(LambdaScope lambdaScope) { ArgumentGuard.NotNull(lambdaScope, nameof(lambdaScope)); LambdaScope = lambdaScope; }
public OrderClauseBuilder(Expression source, LambdaScope lambdaScope, Type extensionType) : base(lambdaScope) { _source = source ?? throw new ArgumentNullException(nameof(source)); _extensionType = extensionType ?? throw new ArgumentNullException(nameof(extensionType)); }
protected QueryClauseBuilder(LambdaScope lambdaScope) { LambdaScope = lambdaScope ?? throw new ArgumentNullException(nameof(lambdaScope)); }