Ejemplo n.º 1
0
        /// <inheritdoc/>
        public override bool Match(PathSegment other)
        {
            TypeSegment otherTypeSegment = other as TypeSegment;

            if (otherTypeSegment == null)
            {
                return(false);
            }

            // Compare the key segment using It's declaring type.
            return(ReferenceEquals(ActualType, otherTypeSegment.ActualType) &&
                   ReferenceEquals(ExpectedType, otherTypeSegment.ExpectedType));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Try to bind namespace-qualified type cast segment.
        /// </summary>
        internal static bool TryBindTypeCastSegment(string identifier, string parenthesisExpressions, IEdmModel model,
                                                    IList <PathSegment> path,
                                                    PathParserSettings settings)
        {
            if (identifier == null || identifier.IndexOf('.') < 0)
            {
                // type cast should be namespace-qualified name
                return(false);
            }

            PathSegment preSegment = path.LastOrDefault();

            if (preSegment == null)
            {
                // type cast should not be the first segment.
                return(false);
            }

            IEdmSchemaType schemaType = model.ResolveType(identifier, settings.EnableCaseInsensitive);

            if (schemaType == null)
            {
                return(false);
            }

            IEdmType targetEdmType = schemaType as IEdmType;

            if (targetEdmType == null)
            {
                return(false);
            }

            IEdmType previousEdmType = preSegment.EdmType;
            bool     isNullable      = false;

            if (previousEdmType.TypeKind == EdmTypeKind.Collection)
            {
                previousEdmType = ((IEdmCollectionType)previousEdmType).ElementType.Definition;
                isNullable      = ((IEdmCollectionType)previousEdmType).ElementType.IsNullable;
            }

            if (!targetEdmType.IsOrInheritsFrom(previousEdmType) && !previousEdmType.IsOrInheritsFrom(targetEdmType))
            {
                throw new Exception($"Type cast {targetEdmType.FullTypeName()} has no relationship with previous {previousEdmType.FullTypeName()}.");
            }

            // We want the type of the type segment to be a collection if the previous segment was a collection
            IEdmType actualTypeOfTheTypeSegment = targetEdmType;

            if (preSegment.EdmType.TypeKind == EdmTypeKind.Collection)
            {
                var actualEntityTypeOfTheTypeSegment = targetEdmType as IEdmEntityType;
                if (actualEntityTypeOfTheTypeSegment != null)
                {
                    actualTypeOfTheTypeSegment = new EdmCollectionType(new EdmEntityTypeReference(actualEntityTypeOfTheTypeSegment, isNullable));
                }
                else
                {
                    // Complex collection supports type cast too.
                    var actualComplexTypeOfTheTypeSegment = actualTypeOfTheTypeSegment as IEdmComplexType;
                    if (actualComplexTypeOfTheTypeSegment != null)
                    {
                        actualTypeOfTheTypeSegment = new EdmCollectionType(new EdmComplexTypeReference(actualComplexTypeOfTheTypeSegment, isNullable));
                    }
                    else
                    {
                        throw new Exception($"Invalid type cast of {identifier}, it should be entity or complex.");
                    }
                }
            }

            TypeSegment typeCast = new TypeSegment(actualTypeOfTheTypeSegment, preSegment.EdmType, preSegment.NavigationSource, identifier);

            path.Add(typeCast);

            TryBindKeySegment(parenthesisExpressions, path);

            return(true);
        }