private void Translate(OeNavigationSelectItem parentNavigationItem, ExpandedNavigationSelectItem item) { IEdmEntitySetBase entitySet = OeEdmClrHelper.GetEntitySet(_edmModel, item); OeNavigationSelectItemKind kind; if (_notSelected) { kind = OeNavigationSelectItemKind.NotSelected; } else if (item.SelectAndExpand.IsNextLink()) { kind = OeNavigationSelectItemKind.NextLink; } else { kind = OeNavigationSelectItemKind.Normal; } var childNavigationSelectItem = new OeNavigationSelectItem(entitySet, parentNavigationItem, item, kind); childNavigationSelectItem = parentNavigationItem.AddOrGetNavigationItem(childNavigationSelectItem); if (childNavigationSelectItem.Kind == OeNavigationSelectItemKind.NextLink) { return; } foreach (SelectItem selectItemClause in item.SelectAndExpand.SelectedItems) { Translate(childNavigationSelectItem, selectItemClause); } }
public OeSelectTranslator(IEdmModel edmModel, OeJoinBuilder joinBuilder, ODataUri odataUri) { _edmModel = edmModel; _joinBuilder = joinBuilder; _odataUri = odataUri; _rootNavigationItem = new OeNavigationSelectItem(odataUri); }
private static OePropertyAccessor[] GetAccessors(Type clrEntityType, OeNavigationSelectItem navigationItem) { ParameterExpression parameter; UnaryExpression typedAccessorParameter; IReadOnlyList <MemberExpression> propertyExpressions; if (navigationItem.AllSelected) { if (navigationItem.Parent != null && navigationItem.NavigationSelectItem is ExpandedCountSelectItem) { parameter = Expression.Parameter(typeof(Object)); typedAccessorParameter = Expression.Convert(parameter, clrEntityType); propertyExpressions = OeExpressionHelper.GetPropertyExpressions(typedAccessorParameter); return(new[] { OePropertyAccessor.CreatePropertyAccessor(OeEdmClrHelper.CountProperty, propertyExpressions[0], parameter, false) }); } else { return(OePropertyAccessor.CreateFromType(clrEntityType, navigationItem.EntitySet)); } } parameter = Expression.Parameter(typeof(Object)); typedAccessorParameter = Expression.Convert(parameter, clrEntityType); propertyExpressions = OeExpressionHelper.GetPropertyExpressions(typedAccessorParameter); IReadOnlyList <OeStructuralSelectItem> structuralItems = navigationItem.GetStructuralItemsWithNotSelected(); var accessors = new OePropertyAccessor[structuralItems.Count]; for (int i = 0; i < structuralItems.Count; i++) { accessors[i] = OePropertyAccessor.CreatePropertyAccessor(structuralItems[i].EdmProperty, propertyExpressions[i], parameter, structuralItems[i].NotSelected); } return(accessors); }
public OeNavigationSelectItem(IEdmEntitySetBase entitySet, OeNavigationSelectItem parent, ExpandedReferenceSelectItem item, OeNavigationSelectItemKind kind) : this(entitySet, CreatePath(parent.Path, item.PathToNavigationProperty)) { _edmProperty = ((NavigationPropertySegment)item.PathToNavigationProperty.LastSegment).NavigationProperty; _navigationSelectItem = item; EntitySet = entitySet; Kind = kind; Parent = parent; }
private static long?GetTop(OeNavigationSelectItem navigationItem, long?top) { if (navigationItem.PageSize > 0 && (top == null || navigationItem.PageSize < top.GetValueOrDefault())) { top = navigationItem.PageSize; } return(top); }
public IReadOnlyList <IEdmNavigationProperty> GetJoinPath() { var joinPath = new List <IEdmNavigationProperty>(); for (OeNavigationSelectItem navigationItem = this; navigationItem.Parent != null; navigationItem = navigationItem.Parent) { joinPath.Insert(0, navigationItem.EdmProperty !); } return(joinPath); }
private void BuildOrderBySkipTake(OeNavigationSelectItem navigationItem, OrderByClause orderByClause, bool hasSelectItems) { while (orderByClause != null) { var propertyNode = (SingleValuePropertyAccessNode)orderByClause.Expression; if (propertyNode.Source is SingleNavigationNode navigationNode) { OeNavigationSelectItem match; ExpandedNavigationSelectItem navigationSelectItem = null; do { if ((match = navigationItem.FindHierarchyNavigationItem(navigationNode.NavigationProperty)) != null) { match.AddStructuralItem((IEdmStructuralProperty)propertyNode.Property, true); break; } SelectExpandClause selectExpandClause; if (navigationSelectItem == null) { var pathSelectItem = new PathSelectItem(new ODataSelectPath(new PropertySegment((IEdmStructuralProperty)propertyNode.Property))); selectExpandClause = new SelectExpandClause(new[] { pathSelectItem }, false); } else { selectExpandClause = new SelectExpandClause(new[] { navigationSelectItem }, false); } var segment = new NavigationPropertySegment(navigationNode.NavigationProperty, navigationNode.NavigationSource); navigationSelectItem = new ExpandedNavigationSelectItem(new ODataExpandPath(segment), navigationNode.NavigationSource, selectExpandClause); }while ((navigationNode = navigationNode.Source as SingleNavigationNode) != null); if (navigationSelectItem != null) { if (match == null) { match = navigationItem; } var selectItemTranslator = new OeSelectItemTranslator(_edmModel, true); selectItemTranslator.Translate(match, navigationSelectItem); } } else { if (hasSelectItems) { navigationItem.AddStructuralItem((IEdmStructuralProperty)propertyNode.Property, true); } } orderByClause = orderByClause.ThenBy; } }
private static void Translate(OeNavigationSelectItem parentNavigationItem, OePageSelectItem pageSelectItem) { if (parentNavigationItem.Parent != null) { var segment = (NavigationPropertySegment)parentNavigationItem.NavigationSelectItem.PathToNavigationProperty.LastSegment; if (!segment.NavigationProperty.Type.IsCollection()) { return; } } parentNavigationItem.PageSize = pageSelectItem.PageSize; }
private static OeNavigationEntryFactory[] GetNestedNavigationLinks(OeNavigationSelectItem navigationItem) { var nestedEntryFactories = new List <OeNavigationEntryFactory>(navigationItem.NavigationItems.Count); for (int i = 0; i < navigationItem.NavigationItems.Count; i++) { if (navigationItem.NavigationItems[i].Kind != OeNavigationSelectItemKind.NotSelected) { nestedEntryFactories.Add((OeNavigationEntryFactory)navigationItem.NavigationItems[i].EntryFactory); } } return(nestedEntryFactories.ToArray()); }
private OeNavigationSelectItem AddOrGetNavigationItem(OeNavigationSelectItem parentNavigationItem, ExpandedReferenceSelectItem item, bool isExpand) { IEdmEntitySetBase entitySet = OeEdmClrHelper.GetEntitySet(_edmModel, item); OeNavigationSelectItemKind kind; if (_notSelected) { kind = OeNavigationSelectItemKind.NotSelected; } else if (item is ExpandedNavigationSelectItem expanded && expanded.SelectAndExpand.IsNextLink()) { kind = OeNavigationSelectItemKind.NextLink; }
private void Translate(OeNavigationSelectItem parentNavigationItem, ExpandedNavigationSelectItem item) { OeNavigationSelectItem childNavigationSelectItem = AddOrGetNavigationItem(parentNavigationItem, item, true); if (childNavigationSelectItem.Kind == OeNavigationSelectItemKind.NextLink) { return; } foreach (SelectItem selectItemClause in item.SelectAndExpand.SelectedItems) { Translate(childNavigationSelectItem, selectItemClause); } }
private Expression GetInnerSource(OeNavigationSelectItem navigationItem) { if (navigationItem.Parent == null) { throw new InvalidOperationException("Inner source cannot exist for root item"); } Type clrEntityType = _edmModel.GetClrType(navigationItem.EdmProperty.DeclaringType); PropertyInfo navigationClrProperty = clrEntityType.GetPropertyIgnoreCase(navigationItem.EdmProperty); Type itemType = OeExpressionHelper.GetCollectionItemTypeOrNull(navigationClrProperty.PropertyType) ?? navigationClrProperty.PropertyType; var visitor = new OeQueryNodeVisitor(_joinBuilder.Visitor, Expression.Parameter(itemType)); var expressionBuilder = new OeExpressionBuilder(_joinBuilder, visitor); IEdmNavigationProperty navigationProperty = navigationItem.EdmProperty; if (navigationItem.EdmProperty.ContainsTarget) { ModelBuilder.ManyToManyJoinDescription joinDescription = _edmModel.GetManyToManyJoinDescription(navigationProperty); navigationProperty = joinDescription.TargetNavigationProperty; } IEdmEntitySet innerEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, navigationProperty); Expression innerSource = OeEnumerableStub.CreateEnumerableStubExpression(itemType, innerEntitySet); ExpandedNavigationSelectItem item = navigationItem.NavigationSelectItem; innerSource = expressionBuilder.ApplyFilter(innerSource, item.FilterOption); long?top = GetTop(navigationItem, item.TopOption); if (top == null && item.SkipOption == null) { return(innerSource); } OrderByClause orderByClause = item.OrderByOption; if (navigationItem.PageSize > 0) { orderByClause = OeSkipTokenParser.GetUniqueOrderBy(navigationItem.EntitySet, item.OrderByOption, null); } var entitySet = (IEdmEntitySet)navigationItem.Parent.EntitySet; Expression source = OeEnumerableStub.CreateEnumerableStubExpression(navigationClrProperty.DeclaringType, entitySet); var crossApplyBuilder = new OeCrossApplyBuilder(_edmModel, expressionBuilder); return(crossApplyBuilder.Build(source, innerSource, navigationItem.Path, orderByClause, item.SkipOption, top)); }
public OeNavigationSelectItem(IEdmEntitySetBase entitySet, OeNavigationSelectItem parent, ExpandedNavigationSelectItem item, OeNavigationSelectItemKind kind) : this() { var segment = (NavigationPropertySegment)item.PathToNavigationProperty.LastSegment; var segments = new List <ODataPathSegment>(parent.Path); segments.AddRange(item.PathToNavigationProperty); EdmProperty = segment.NavigationProperty; EntitySet = entitySet; Kind = kind; NavigationSelectItem = item; Parent = parent; Path = new ODataPath(segments); }
public OeNavigationSelectItem FindHierarchyNavigationItem(IEdmNavigationProperty navigationProperty) { if (EdmProperty == navigationProperty) { return(this); } for (int i = 0; i < _navigationItems.Count; i++) { OeNavigationSelectItem matched = _navigationItems[i].FindHierarchyNavigationItem(navigationProperty); if (matched != null) { return(matched); } } return(null); }
internal OeNavigationSelectItem AddOrGetNavigationItem(OeNavigationSelectItem navigationItem, bool isExpand) { _allSelected &= isExpand; OeNavigationSelectItem?existingNavigationItem = FindChildrenNavigationItem(navigationItem.EdmProperty); if (existingNavigationItem == null) { _navigationItems.Add(navigationItem); return(navigationItem); } if (existingNavigationItem.Kind == OeNavigationSelectItemKind.NotSelected && navigationItem.Kind == OeNavigationSelectItemKind.Normal) { existingNavigationItem.Kind = OeNavigationSelectItemKind.Normal; } return(existingNavigationItem); }
public void Translate(OeNavigationSelectItem parentNavigationItem, SelectItem item) { if (item is ExpandedNavigationSelectItem expandedNavigationSelectItem) { Translate(parentNavigationItem, expandedNavigationSelectItem); } else if (item is PathSelectItem pathSelectItem) { Translate(parentNavigationItem, pathSelectItem); } else if (item is OePageSelectItem pageSelectItem) { Translate(parentNavigationItem, pageSelectItem); } else { throw new InvalidOperationException("Unknown SelectItem type " + item.GetType().Name); } }
internal OeNavigationSelectItem AddOrGetNavigationItem(OeNavigationSelectItem navigationItem) { OeNavigationSelectItem existingNavigationItem = FindChildrenNavigationItem(navigationItem.EdmProperty); if (existingNavigationItem == null) { _navigationItems.Add(navigationItem); return(navigationItem); } if (existingNavigationItem.Kind == OeNavigationSelectItemKind.NotSelected && navigationItem.Kind == OeNavigationSelectItemKind.Normal) { existingNavigationItem.Kind = OeNavigationSelectItemKind.Normal; } else if (existingNavigationItem.StructuralItems.Count == 0) { existingNavigationItem._selectAll = true; } return(existingNavigationItem); }
private static OePropertyAccessor[] GetAccessors(Type clrEntityType, OeNavigationSelectItem navigationItem) { if (navigationItem.StructuralItems.Count == 0) { return(OePropertyAccessor.CreateFromType(clrEntityType, navigationItem.EntitySet)); } IReadOnlyList <OeStructuralSelectItem> structuralItems = navigationItem.GetStructuralItemsWithNotSelected(); var accessors = new OePropertyAccessor[structuralItems.Count]; ParameterExpression parameter = Expression.Parameter(typeof(Object)); UnaryExpression typedAccessorParameter = Expression.Convert(parameter, clrEntityType); IReadOnlyList <MemberExpression> propertyExpressions = OeExpressionHelper.GetPropertyExpressions(typedAccessorParameter); for (int i = 0; i < structuralItems.Count; i++) { accessors[i] = OePropertyAccessor.CreatePropertyAccessor(structuralItems[i].EdmProperty, propertyExpressions[i], parameter, structuralItems[i].NotSelected); } return(accessors); }
private void Translate(OeNavigationSelectItem parentNavigationItem, PathSelectItem item) { if (item.SelectedPath.LastSegment is NavigationPropertySegment navigationSegment) { IEdmNavigationSource navigationSource = navigationSegment.NavigationSource; if (navigationSource == null) { navigationSource = OeEdmClrHelper.GetEntitySet(_edmModel, navigationSegment.NavigationProperty); } var expandedItem = new ExpandedNavigationSelectItem(new ODataExpandPath(item.SelectedPath), navigationSource, new SelectExpandClause(null, true)); AddOrGetNavigationItem(parentNavigationItem, expandedItem, false); } else if (item.SelectedPath.LastSegment is PropertySegment propertySegment) { parentNavigationItem.AddStructuralItem(propertySegment.Property, _notSelected); } else { throw new InvalidOperationException(item.SelectedPath.LastSegment.GetType().Name + " not supported"); } }
private static List <OeNavigationSelectItem> FlattenNavigationItems(OeNavigationSelectItem root, bool includeNextLink) { var navigationItems = new List <OeNavigationSelectItem>(); var stack = new Stack <ValueTuple <OeNavigationSelectItem, int> >(); stack.Push(new ValueTuple <OeNavigationSelectItem, int>(root, 0)); do { ValueTuple <OeNavigationSelectItem, int> stackItem = stack.Pop(); if (stackItem.Item2 == 0 && (includeNextLink || stackItem.Item1.Kind != OeNavigationSelectItemKind.NextLink)) { navigationItems.Add(stackItem.Item1); } if (stackItem.Item2 < stackItem.Item1.NavigationItems.Count) { stack.Push(new ValueTuple <OeNavigationSelectItem, int>(stackItem.Item1, stackItem.Item2 + 1)); OeNavigationSelectItem selectItem = stackItem.Item1.NavigationItems[stackItem.Item2]; stack.Push(new ValueTuple <OeNavigationSelectItem, int>(selectItem, 0)); } }while (stack.Count > 0); return(navigationItems); }
private OeNavigationSelectItem AddOrGetNavigationItem(OeNavigationSelectItem parentNavigationItem, ExpandedNavigationSelectItem item, bool isExpand) { IEdmEntitySetBase entitySet = OeEdmClrHelper.GetEntitySet(_edmModel, item); OeNavigationSelectItemKind kind; if (_notSelected) { kind = OeNavigationSelectItemKind.NotSelected; } else if (item.SelectAndExpand.IsNextLink()) { kind = OeNavigationSelectItemKind.NextLink; } else { kind = OeNavigationSelectItemKind.Normal; } var childNavigationSelectItem = new OeNavigationSelectItem(entitySet, parentNavigationItem, item, kind); return(parentNavigationItem.AddOrGetNavigationItem(childNavigationSelectItem, isExpand)); }
private Expression BuildJoin(Expression source, IList <OeNavigationSelectItem> navigationItems) { for (int i = 1; i < navigationItems.Count; i++) { OeNavigationSelectItem navigationItem = navigationItems[i]; if (navigationItem.Parent == null) { throw new InvalidOperationException("Parent is null must be first element in " + nameof(navigationItems)); } if (!navigationItem.AlreadyUsedInBuildExpression) { navigationItem.AlreadyUsedInBuildExpression = true; ODataPathSegment segment = navigationItem.NavigationSelectItem.PathToNavigationProperty.LastSegment; IEdmNavigationProperty navigationProperty = (((NavigationPropertySegment)segment).NavigationProperty); Expression innerSource = GetInnerSource(navigationItem); source = _joinBuilder.Build(_edmModel, source, innerSource, navigationItem.Parent.GetJoinPath(), navigationProperty); } } _joinBuilder.Visitor.ChangeParameterType(source); return(source); }
internal MethodCallExpression BuildExpandCount(Expression outer, Expression inner, OeNavigationSelectItem navigationItem) { IEdmNavigationProperty navigationProperty = navigationItem.EdmProperty; if (navigationItem.EdmProperty.ContainsTarget) { throw new InvalidOperationException("Expand cout for many-tomany not supported"); } Type outerType = OeExpressionHelper.GetCollectionItemType(outer.Type); Type innerType = OeExpressionHelper.GetCollectionItemType(inner.Type); ParameterExpression outerParameter = Expression.Parameter(outerType, outerType.Name); IReadOnlyList <IEdmNavigationProperty> joinPath = navigationItem.Parent == null?Array.Empty <IEdmNavigationProperty>() : navigationItem.Parent.GetJoinPath(); Expression?joinPropertyExpression = _expressionBuilder.JoinBuilder.GetJoinPropertyExpression(outerParameter, joinPath); if (joinPropertyExpression == null) { throw new InvalidOperationException("Outer source not found"); } MethodCallExpression subquery = CreateWhereExpression(joinPropertyExpression, inner, navigationProperty); MethodInfo methodInfo = OeMethodInfoHelper.GetCountMethodInfo(innerType); subquery = Expression.Call(methodInfo, subquery); List <Expression> expressions = new List <Expression>(); if (OeExpressionHelper.IsTupleType(outerParameter.Type)) { expressions.AddRange(OeExpressionHelper.GetPropertyExpressions(outerParameter)); } else { expressions.Add(outerParameter); } expressions.Add(OeExpressionHelper.CreateTupleExpression(new[] { subquery })); NewExpression newTuple = OeExpressionHelper.CreateTupleExpression(expressions); methodInfo = OeMethodInfoHelper.GetSelectMethodInfo(outerType, newTuple.Type); return(Expression.Call(methodInfo, outer, Expression.Lambda(newTuple, outerParameter))); }
private static OeEntryFactory CreateEntryFactory(OeNavigationSelectItem root, Type clrType, OePropertyAccessor[] skipTokenAccessors) { ParameterExpression parameter = Expression.Parameter(typeof(Object)); UnaryExpression typedParameter = Expression.Convert(parameter, clrType); if (!root.HasNavigationItems()) { var navigationLinks = new OeEntryFactory[root.NavigationItems.Count]; for (int i = 0; i < root.NavigationItems.Count; i++) { OeNavigationSelectItem navigationItem = root.NavigationItems[i]; var nextLinkOptions = new OeEntryFactoryOptions() { Accessors = Array.Empty <OePropertyAccessor>(), EdmNavigationProperty = navigationItem.EdmProperty, EntitySet = navigationItem.EntitySet, NavigationSelectItem = navigationItem.NavigationSelectItem, NextLink = navigationItem.Kind == OeNavigationSelectItemKind.NextLink }; navigationLinks[i] = new OeEntryFactory(ref nextLinkOptions); } var options = new OeEntryFactoryOptions() { Accessors = GetAccessors(clrType, root), EntitySet = root.EntitySet, NavigationLinks = navigationLinks, SkipTokenAccessors = skipTokenAccessors }; root.EntryFactory = new OeEntryFactory(ref options); } else { List <OeNavigationSelectItem> navigationItems = FlattenNavigationItems(root, true); IReadOnlyList <MemberExpression> navigationProperties = OeExpressionHelper.GetPropertyExpressions(typedParameter); int propertyIndex = navigationProperties.Count - 1; for (int i = navigationItems.Count - 1; i >= 0; i--) { OeNavigationSelectItem navigationItem = navigationItems[i]; if (navigationItem.Kind == OeNavigationSelectItemKind.NotSelected) { propertyIndex--; continue; } OePropertyAccessor[] accessors = Array.Empty <OePropertyAccessor>(); LambdaExpression? linkAccessor = null; OeEntryFactory[] nestedNavigationLinks = Array.Empty <OeEntryFactory>(); if (navigationItem.Kind != OeNavigationSelectItemKind.NextLink) { accessors = GetAccessors(navigationProperties[propertyIndex].Type, navigationItem); linkAccessor = Expression.Lambda(navigationProperties[propertyIndex], parameter); nestedNavigationLinks = GetNestedNavigationLinks(navigationItem); propertyIndex--; } var options = new OeEntryFactoryOptions() { Accessors = accessors, EdmNavigationProperty = navigationItem.Parent == null ? null : navigationItem.EdmProperty, EntitySet = navigationItem.EntitySet, LinkAccessor = linkAccessor, NavigationLinks = nestedNavigationLinks, NavigationSelectItem = navigationItem.Parent == null ? null : navigationItem.NavigationSelectItem, NextLink = navigationItem.Kind == OeNavigationSelectItemKind.NextLink, SkipTokenAccessors = skipTokenAccessors }; navigationItem.EntryFactory = new OeEntryFactory(ref options); } } return(root.EntryFactory); }
private static Expression SelectStructuralProperties(Expression source, OeNavigationSelectItem root) { if (!root.HasNavigationItems()) { return(source); } ParameterExpression parameter = Expression.Parameter(OeExpressionHelper.GetCollectionItemType(source.Type)); IReadOnlyList <MemberExpression> joins = OeExpressionHelper.GetPropertyExpressions(parameter); var newJoins = new Expression[joins.Count]; List <OeNavigationSelectItem> navigationItems = FlattenNavigationItems(root, false); bool isNavigationNullable = false; for (int i = 0; i < navigationItems.Count; i++) { newJoins[i] = joins[i]; isNavigationNullable |= i > 0 && navigationItems[i].EdmProperty.Type.IsNullable; if (!navigationItems[i].AllSelected) { IReadOnlyList <OeStructuralSelectItem> structuralItems = navigationItems[i].GetStructuralItemsWithNotSelected(); if (structuralItems.Count > 0) { var properties = new Expression[structuralItems.Count]; for (int j = 0; j < structuralItems.Count; j++) { if (structuralItems[j].EdmProperty is ComputeProperty computeProperty) { properties[j] = new ReplaceParameterVisitor(joins[i]).Visit(computeProperty.Expression); } else { PropertyInfo property = joins[i].Type.GetPropertyIgnoreCase(structuralItems[j].EdmProperty); properties[j] = Expression.Property(joins[i], property); } } Expression newTupleExpression = OeExpressionHelper.CreateTupleExpression(properties); if (isNavigationNullable) { UnaryExpression nullConstant = Expression.Convert(OeConstantToVariableVisitor.NullConstantExpression, newTupleExpression.Type); newTupleExpression = Expression.Condition(Expression.Equal(joins[i], OeConstantToVariableVisitor.NullConstantExpression), nullConstant, newTupleExpression); } newJoins[i] = newTupleExpression; } } } NewExpression newSelectorBody = OeExpressionHelper.CreateTupleExpression(newJoins); MethodInfo selectMethodInfo = OeMethodInfoHelper.GetSelectMethodInfo(parameter.Type, newSelectorBody.Type); LambdaExpression newSelector = Expression.Lambda(newSelectorBody, parameter); //Quirk EF Core 2.1.1 bug Take/Skip must be last in expression tree var skipTakeExpressions = new List <MethodCallExpression>(); while (source is MethodCallExpression callExpression && (callExpression.Method.Name == nameof(Enumerable.Skip) || callExpression.Method.Name == nameof(Enumerable.Take))) { skipTakeExpressions.Add(callExpression); source = callExpression.Arguments[0]; } source = Expression.Call(selectMethodInfo, source, newSelector); for (int i = skipTakeExpressions.Count - 1; i >= 0; i--) { MethodInfo skipTakeMethodInfo = skipTakeExpressions[i].Method.GetGenericMethodDefinition().MakeGenericMethod(newSelector.ReturnType); source = Expression.Call(skipTakeMethodInfo, source, skipTakeExpressions[i].Arguments[1]); } return(source); }
public override OeEntryFactory CreateEntryFactory(IEdmEntitySet entitySet, Type clrType, OePropertyAccessor[]?skipTokenAccessors) { ParameterExpression parameter = Expression.Parameter(typeof(Object)); UnaryExpression typedParameter = Expression.Convert(parameter, clrType); if (_rootNavigationItem.HasNavigationItems()) { List <OeNavigationSelectItem> navigationItems = OeSelectTranslator.FlattenNavigationItems(_rootNavigationItem, true); IReadOnlyList <MemberExpression> navigationProperties = OeExpressionHelper.GetPropertyExpressions(typedParameter); int propertyIndex = navigationProperties.Count - 1; for (int i = navigationItems.Count - 1; i >= 0; i--) { OeNavigationSelectItem navigationItem = navigationItems[i]; if (navigationItem.Kind == OeNavigationSelectItemKind.NotSelected) { propertyIndex--; continue; } OePropertyAccessor[] accessors = Array.Empty <OePropertyAccessor>(); LambdaExpression? linkAccessor = null; OeNavigationEntryFactory[] nestedNavigationLinks = Array.Empty <OeNavigationEntryFactory>(); if (navigationItem.Kind != OeNavigationSelectItemKind.NextLink) { accessors = GetAccessors(navigationProperties[propertyIndex].Type, navigationItem); linkAccessor = Expression.Lambda(navigationProperties[propertyIndex], parameter); nestedNavigationLinks = GetNestedNavigationLinks(navigationItem); propertyIndex--; } if (i == 0) { navigationItem.EntryFactory = new OeEntryFactory(navigationItem.EntitySet, accessors, skipTokenAccessors, nestedNavigationLinks, linkAccessor); } else { navigationItem.EntryFactory = new OeNavigationEntryFactory( navigationItem.EntitySet, accessors, skipTokenAccessors, nestedNavigationLinks, linkAccessor, navigationItem.EdmProperty, navigationItem.NavigationSelectItem, navigationItem.Kind == OeNavigationSelectItemKind.NextLink); } } } else { var navigationLinks = new OeNavigationEntryFactory[_rootNavigationItem.NavigationItems.Count]; for (int i = 0; i < _rootNavigationItem.NavigationItems.Count; i++) { OeNavigationSelectItem navigationItem = _rootNavigationItem.NavigationItems[i]; navigationLinks[i] = new OeNavigationEntryFactory( navigationItem.EntitySet, Array.Empty <OePropertyAccessor>(), null, Array.Empty <OeNavigationEntryFactory>(), null, navigationItem.EdmProperty, navigationItem.NavigationSelectItem, navigationItem.Kind == OeNavigationSelectItemKind.NextLink); } OePropertyAccessor[] accessors = GetAccessors(clrType, _rootNavigationItem); _rootNavigationItem.EntryFactory = new OeEntryFactory(_rootNavigationItem.EntitySet, accessors, skipTokenAccessors, navigationLinks); } return(_rootNavigationItem.EntryFactory); }
public OeSelectEntryFactoryFactory(OeNavigationSelectItem rootNavigationItem) { _rootNavigationItem = rootNavigationItem; }