コード例 #1
0
        /// <summary>
        /// Try to get the mapped type from the given expression. When the <paramref name="expression"/> type is
        /// <see cref="ExpressionType.Convert"/>, the <paramref name="mappedType"/> will be set based on the expression type
        /// only when the mapping for <see cref="UnaryExpression.Operand"/> was found, otherwise <see langword="null"/>
        /// will be returned.
        /// </summary>
        /// <param name="sessionFactory">The session factory to retrieve <see cref="IEntityPersister"/> types.</param>
        /// <param name="expression">The expression to evaluate.</param>
        /// <param name="mappedType">Output parameter that represents the mapped type of <paramref name="memberPath"/>.</param>
        /// <param name="entityPersister">
        /// Output parameter that represents the entity persister of the entity where <paramref name="memberPath"/> is defined.
        /// This parameter will not be set when <paramref name="memberPath"/> represents a property in a collection composite element.
        /// </param>
        /// <param name="component">
        /// Output parameter that represents the component type where <paramref name="memberPath"/> is defined.
        /// This parameter will not be set when <paramref name="memberPath"/> does not represent a property in a component.
        /// </param>
        /// <param name="memberPath">
        /// Output parameter that represents the path of the mapped member, which in most cases is the member name. In case
        /// when the mapped member is defined inside a component the path will be prefixed with the name of the component member and a dot.
        /// (e.g. Component.Property).</param>
        /// <returns>Whether the mapped type was found.</returns>
        /// <remarks>
        /// When the <paramref name="expression"/> contains an expression of type <see cref="ExpressionType.Convert"/>, the
        /// result may not be correct when casting to an entity that is mapped with multiple entity names.
        /// When the <paramref name="expression"/> is polymorphic, the first implementor will be returned.
        /// When the <paramref name="expression"/> contains a <see cref="ConditionalExpression"/>, the first found entity name
        /// will be returned from <see cref="ConditionalExpression.IfTrue"/> or <see cref="ConditionalExpression.IfFalse"/>.
        /// When the <paramref name="expression"/> contains a <see cref="ExpressionType.Coalesce"/> expression, the first found entity name
        /// will be returned from <see cref="BinaryExpression.Left"/> or <see cref="BinaryExpression.Right"/>.
        /// </remarks>
        internal static bool TryGetMappedType(
            ISessionFactoryImplementor sessionFactory,
            Expression expression,
            out IType mappedType,
            out IEntityPersister entityPersister,
            out IAbstractComponentType component,
            out string memberPath)
        {
            // In order to get the correct entity name from the expression we first have to find the constant expression that contains the
            // IEntityNameProvider instance, from which we can retrieve the starting entity name. Once we have it, we have to traverse all
            // expressions that we had to traverse in order to find the IEntityNameProvider instance, but in reverse order (bottom to top)
            // and keep tracking the entity name until we reach to top.

            memberPath      = null;
            mappedType      = null;
            entityPersister = null;
            component       = null;
            // Try to retrieve the starting entity name with all members that were traversed in that process.
            if (!MemberMetadataExtractor.TryGetAllMemberMetadata(expression, out var metadataResults))
            {
                // Failed to find the starting entity name, due to:
                // - Unsupported expression
                // - The expression didn't contain the IEntityNameProvider instance
                return(false);
            }

            // Due to coalesce and conditional expressions we can have multiple paths to traverse, in that case find the first path
            // for which we are able to determine the mapped type.
            foreach (var metadataResult in metadataResults)
            {
                if (ProcessMembersMetadataResult(
                        metadataResult,
                        sessionFactory,
                        out mappedType,
                        out entityPersister,
                        out component,
                        out memberPath))
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #2
0
            private static bool TryGetAllMemberMetadata(
                Expression expression,
                Stack <MemberMetadata> memberPaths,
                System.Type convertType,
                bool hasIndexer,
                out MemberMetadataResult results)
            {
                var extractor = new MemberMetadataExtractor(memberPaths, convertType, hasIndexer);

                extractor.Accept(expression);
                results = extractor._entityName != null || extractor._childrenResults.Count > 0
                                        ? new MemberMetadataResult(
                    extractor._childrenResults,
                    extractor._memberPaths,
                    extractor._entityName,
                    extractor._convertType)
                                        : null;

                return(results != null);
            }