TypeResolver.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Common / EntitySql / TypeResolver.cs / 3 / TypeResolver.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backup [....] 
//--------------------------------------------------------------------- 

 
namespace System.Data.Common.EntitySql
{
    using System;
    using System.Globalization; 
    using System.Collections.Generic;
    using System.Text; 
    using System.Diagnostics; 
    using System.Data.Common;
    using System.Data.Metadata.Edm; 
    using System.Data.Entity;

    /// 
    /// Represents Type Resolver Helper in the context of a typespace 
    /// 
    internal sealed class TypeResolver 
    { 
        private TypeUsage _cachedStringType;
        private TypeUsage _cachedBooleanType; 
        private TypeUsage _cachedInt64Type;
        private Perspective _perspective;
        private Dictionary _aliasedNamespaces;
        private HashSet _namespaces; 

        ///  
        /// Initializes TypeResolver instance 
        /// 
        ///  
        /// 
        internal TypeResolver( Perspective perspective, StringComparer stringComparer )
        {
            EntityUtil.CheckArgumentNull(perspective, "perspective"); 

            _perspective = perspective; 
 
            _aliasedNamespaces = new Dictionary(stringComparer);
 
            _namespaces = new HashSet(stringComparer);
        }

        ///  
        /// returns perspective instance
        ///  
        internal Perspective Perspective 
        {
            get { return _perspective; } 
        }

        /// 
        /// Add aliased namespace declaration 
        /// 
        ///  
        ///  
        internal bool TryAddAliasedNamespace( string alias, string namespaceName )
        { 
            if (_aliasedNamespaces.ContainsKey(alias))
            {
                return false;
            } 

            _aliasedNamespaces.Add(alias, namespaceName); 
 
            return true;
        } 


        /// 
        /// Add namespaces declaration 
        /// 
        ///  
        internal bool TryAddNamespace( string namespaceName ) 
        {
            if (_namespaces.Contains(namespaceName)) 
            {
                return false;
            }
 
            _namespaces.Add(namespaceName);
 
            return true; 
        }
 
        /// 
        /// returns true if key type is valid for collation
        /// 
        ///  
        /// 
        internal static bool IsKeyValidForCollation( TypeUsage type ) 
        { 
            return (TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.String) /* && isSearchable */ );
        } 

        /// 
        /// returns if a given type is allowed to have method calls
        ///  
        /// 
        ///  
        internal static bool IsValidTypeForMethodCall( TypeUsage type ) 
        {
            return (type.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType); 
        }

        /// 
        /// returns true if type is string type 
        /// 
        ///  
        ///  
        internal static bool IsStringType( TypeUsage type )
        { 
            return TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.String);
        }

        ///  
        /// Checks if a type is boolean
        ///  
        ///  
        /// 
        internal static bool IsBooleanType( TypeUsage type ) 
        {
            return TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.Boolean);
        }
 
        /// 
        /// Checks if two types are sub/super type inclusive 
        ///  
        /// 
        ///  
        /// 
        internal static bool IsSubOrSuperType( TypeUsage type1, TypeUsage type2 )
        {
            return TypeSemantics.IsEquivalent(type1, type2) || type1.IsSubtypeOf(type2) || type2.IsSubtypeOf(type1); 
        }
 
        ///  
        /// returns target space Edm.String type
        ///  
        internal TypeUsage StringType
        {
            get
            { 
                if (null == _cachedStringType)
                { 
                    _cachedStringType = _perspective.MetadataWorkspace.GetCanonicalModelTypeUsage(PrimitiveTypeKind.String); 
                }
                return _cachedStringType; 
            }
        }

        ///  
        /// returns target space Edm.Booelan type
        ///  
        internal TypeUsage BooleanType 
        {
            get 
            {
                if (null == _cachedBooleanType)
                {
                    _cachedBooleanType = _perspective.MetadataWorkspace.GetCanonicalModelTypeUsage(PrimitiveTypeKind.Boolean); 
                }
                return _cachedBooleanType; 
            } 
        }
 
        /// 
        /// returns target space Edm.Int64 type
        /// 
        internal TypeUsage Int64Type 
        {
            get 
            { 
                if (null == _cachedInt64Type)
                { 
                    _cachedInt64Type = _perspective.MetadataWorkspace.GetCanonicalModelTypeUsage(PrimitiveTypeKind.Int64);
                }
                return _cachedInt64Type;
            } 
        }
 
        ///  
        /// resolves a name as type
        ///  
        /// 
        /// 
        /// 
        /// TypeUsage 
        internal TypeUsage ResolveNameAsType( string[] names, int countNames, out int matchCount )
        { 
            TypeUsage TypeUsage = null; 
            matchCount = 0;
 
            //
            // lookup type in aliased namespaces if aliased
            //
            if (names.Length > 1 && (countNames > (names.Length - 1))) 
            {
                string namespaceName = null; 
                if (_aliasedNamespaces.TryGetValue(names[0], out namespaceName)) 
                {
                    if (TryGetTypeFromMetadata(namespaceName + "." + ConcatStringsWithSeparator(names, '.', 1, countNames - 1), out TypeUsage)) 
                    {
                        matchCount = 1;
                        return TypeUsage;
                    } 
                }
            } 
 
            string typeName = ConcatStringsWithSeparator(names, '.', 0, countNames);
 
            //
            // Try Full type name
            //
            if (TryGetTypeFromMetadata(typeName, out TypeUsage)) 
            {
                matchCount = 1; 
                return TypeUsage; 
            }
 
            //
            // lookup type in namespaces
            //
            TypeUsage matchType; 
            foreach (string ns in _namespaces)
            { 
                if (TryGetTypeFromMetadata(ns + "." + typeName, out matchType)) 
                {
                    matchCount++; 
                    TypeUsage = matchType;
                }
            }
 
            return TypeUsage;
        } 
 
        /// 
        /// Resolves a Name as Function 
        /// 
        /// 
        /// 
        ///  
        /// 
        ///  
        internal IList ResolveNameAsFunction( string[] names, bool ignoreCase, out int matchCount, 
            out List foundNamespaces)
        { 
            IList functionList = null;
            foundNamespaces = new List();
            string namespaceName = null;
            string functionName = names[names.Length - 1]; 
            matchCount = 0;
 
            // 
            // lookup type in aliased namespaces if aliased
            // 
            if (names.Length > 1)
            {
                if (_aliasedNamespaces.TryGetValue(names[0], out namespaceName))
                { 
                    if (TryGetFunctionFromMetadata(functionName, namespaceName, ignoreCase, out functionList))
                    { 
                        matchCount = 1; 
                        foundNamespaces.Add(namespaceName);
                        return functionList; 
                    }
                }

                // 
                // Try function full name
                // 
                namespaceName = ConcatStringsWithSeparator(names, '.', 0, names.Length - 1); 
                if (TryGetFunctionFromMetadata(functionName, namespaceName, ignoreCase, out functionList))
                { 
                    matchCount = 1;
                    foundNamespaces.Add(namespaceName);
                }
 
                return functionList;
            } 
 
            //
            // lookup type in namespaces 
            //
            IList tmpFunctionList;
            foreach (string ns in _namespaces)
            { 
                if (TryGetFunctionFromMetadata(functionName, ns, ignoreCase, out tmpFunctionList))
                { 
                    matchCount++; 
                    functionList = tmpFunctionList;
                    foundNamespaces.Add(ns); 
                }
            }

            return functionList; 
        }
 
        ///  
        /// find name base type
        ///  
        /// 
        /// 
        /// 
        ///  
        internal TypeUsage ResolveBaseType( string[] names, out int suffixIndex, out int matchCount )
        { 
            TypeUsage TypeUsage = null; 
            suffixIndex = 0;
            matchCount = 0; 

            Debug.Assert(names.Length > 0, "names.Length > 0");

            // 
            // lookup in aliased namespaces
            // 
            if (!TryGetBaseTypeInAliasedNamespaces(names, out TypeUsage, out suffixIndex)) 
            {
 
                //
                // Try Resolve id base type
                //
                int idMatchCount = 0; 
                int idSuffix = 0;
                TypeUsage idTypeUsage; 
                if (TryGetIdentifierBaseType(names, out idTypeUsage, out idSuffix)) 
                {
                    idMatchCount++; 
                }

                //
                // lookup in known namespaces 
                //
                if (TryGetBaseTypeInNamespaces(names, out TypeUsage, out suffixIndex, out matchCount)) 
                { 
                    matchCount += idMatchCount;
                } 

                if (null == TypeUsage)
                {
                    TypeUsage = idTypeUsage; 
                    suffixIndex = idSuffix;
                    matchCount = idMatchCount; 
                } 

            } 

            return TypeUsage;
        }
 
        /// 
        /// given an identifier try to get its base type 
        ///  
        /// 
        ///  
        /// 
        /// 
        internal bool TryGetIdentifierBaseType( string[] names, out TypeUsage TypeUsage, out int suffixIndex )
        { 
            TypeUsage = null;
            suffixIndex = 0; 
            System.Text.StringBuilder sb = new System.Text.StringBuilder(); 
            for(int i=0; i < names.Length; i++)
            { 
                sb.Append(names[i]);
                if (TryGetTypeFromMetadata(sb.ToString(), out TypeUsage))
                {
                    suffixIndex = i; 
                    return true;
                } 
                sb.Append('.'); 
            }
            return false; 
        }


        ///  
        /// try resolve base type in aliased namespaces
        ///  
        ///  
        /// 
        ///  
        /// 
        internal bool TryGetBaseTypeInAliasedNamespaces( string[] names, out TypeUsage TypeUsage, out int suffixIndex )
        {
            TypeUsage = null; 
            suffixIndex = 0;
 
            if (names.Length > 1) 
            {
                string namespaceName = null; 
                if (_aliasedNamespaces.TryGetValue(names[0], out namespaceName))
                {
                    if (TryGetBaseTypeFromMetadata(namespaceName, TrimNamesPrefix(names, 1), out TypeUsage, out suffixIndex))
                    { 
                        suffixIndex++;
                        return true; 
                    } 
                }
            } 

            return false;
        }
 

        ///  
        /// try resolve Base type in declared non-aliased namespaces 
        /// 
        ///  
        /// 
        /// 
        /// 
        ///  
        internal bool TryGetBaseTypeInNamespaces( string[] names, out TypeUsage TypeUsage, out int suffixIndex, out int matchCount )
        { 
            TypeUsage = null; 
            suffixIndex = 0;
            matchCount = 0; 
            TypeUsage matchType = null;

            foreach (string nsPrefix in _namespaces)
            { 
                if (TryGetTypeFromMetadata(nsPrefix + "." + names[0], out TypeUsage))
                { 
                    matchType = TypeUsage; 
                    suffixIndex = 1;
                    matchCount++; 
                }
            }

            TypeUsage = matchType; 
            return (matchCount > 0);
        } 
 

        ///  
        /// try get base type from metadata
        /// 
        /// 
        ///  
        /// 
        ///  
        ///  
        internal bool TryGetBaseTypeFromMetadata( string namespaceName, string[] names, out TypeUsage TypeUsage, out int suffixIndex )
        { 
            TypeUsage = null;
            suffixIndex = 0;

            if (TryGetTypeFromMetadata(namespaceName + "." + names[0], out TypeUsage)) 
            {
                suffixIndex = 1; 
            } 

            return (null != TypeUsage); 
        }

        /// 
        /// Lookup metadata for a function given its fqn 
        /// 
        ///  
        ///  
        /// 
        ///  
        /// 
        internal bool TryGetFunctionFromMetadata(string name, string namespaceName, bool ignoreCase,
            out IList functionMetadata)
        { 
            System.Collections.ObjectModel.ReadOnlyCollection functions =
                _perspective.GetFunctions(name, namespaceName, ignoreCase); 
 
            functionMetadata = functions;
            if (functionMetadata.Count > 0) 
            {
                return true;
            }
            return false; 
        }
 
 
        /// 
        /// Get global function metadata 
        /// 
        /// 
        /// 
        ///  
        /// 
        /// Funciton metadata 
        internal static EdmFunction ResolveFunctionOverloads( IList functionsMetadata, 
                                                              IList argTypes,
                                                              bool isGroupAggregateFunction, 
                                                              out bool isAmbiguous )
        {
            EdmFunction closestFunctionMatch = null;
            uint maxRank = 0; 
            isAmbiguous = false;
 
            Debug.Assert(functionsMetadata.Count > 0, "functionsMetadata.Count must be greater than zero"); 

            for (int i = 0 ; i < functionsMetadata.Count ; i++) 
            {
                uint rank = RankFunctionParameters(argTypes,
                                                   functionsMetadata[i].Parameters,
                                                   isGroupAggregateFunction); 

                if (0 == rank) 
                { 
                    continue;
                } 

                if (rank == maxRank)
                {
                    isAmbiguous = true; 
                }
 
                if (rank > maxRank) 
                {
                    isAmbiguous = false; 
                    maxRank = rank;
                    closestFunctionMatch = functionsMetadata[i];
                }
            } 

            return closestFunctionMatch; 
        } 

 
        /// 
        /// Ranks a list of candidate parameter types against the function formal signature especification
        /// 
        /// list of candidate parameter types 
        /// function formal signature parameter metadata
        ///  
        ///  
        /// assumes no overload will have more than 10^12 equivalent parameters
        static internal uint RankFunctionParameters(  IList candidateParams, 
                                                      IList signatureParams,
                                                      bool isGroupAggregateFunction )
        {
            if (candidateParams.Count != signatureParams.Count) 
            {
                return 0; 
            } 

            if (0 == candidateParams.Count && 0 == signatureParams.Count) 
            {
                return 0X40000000;
            }
 
            int equivalenceCount = 0;
            int promotionCount = 0; 
            for (int i = 0 ; i < candidateParams.Count ; i++) 
            {
                TypeUsage candidateParamType = candidateParams[i]; 
                TypeUsage formalParamType = signatureParams[i].TypeUsage;
                //
                // if function being ranked is a group aggregate, consider the element type
                // 
                if (isGroupAggregateFunction)
                { 
                    if (!TypeSemantics.IsCollectionType(formalParamType)) 
                    {
                        // 
                        // even though it is the job of metadata to ensure that the provider manifest is consistent
                        // ensure that if a function is marked as aggregate, then the argument type must be of collection{GivenType}
                        //
                        throw EntityUtil.EntitySqlError(Strings.InvalidArgumentTypeForAggregateFunction); 
                    }
                    formalParamType = TypeHelpers.GetElementTypeUsage(formalParamType); 
                } 

                if (signatureParams[i].Mode != ParameterMode.In && signatureParams[i].Mode != ParameterMode.InOut) 
                {
                    return 0;
                }
 
                if (TypeSemantics.IsEquivalent(candidateParamType, formalParamType) ||
                   (TypeSemantics.IsNullType(candidateParamType) && !TypeSemantics.IsCollectionType(formalParamType))) 
                { 
                    equivalenceCount++;
                } 
                else if (TypeSemantics.IsPromotableTo(candidateParamType, formalParamType))
                {
                    promotionCount += GetPromotionRank(candidateParamType, formalParamType);
                } 
                else
                { 
                    return 0; 
                }
            } 

            if (equivalenceCount >= 0x8000 || promotionCount >= 0x8000)
            {
                throw EntityUtil.EntitySqlError(Strings.TooManyFunctionArguments); 
            }
 
            return (uint)((equivalenceCount << 15) | promotionCount); 
        }
 

        /// 
        /// Assume that candidateType *IS PROMOTABLE* to formalType
        ///  
        /// 
        ///  
        ///  
        static private int GetPromotionRank( TypeUsage candidateType, TypeUsage formalType )
        { 
            int promotionRank = 1;

            Debug.Assert(TypeSemantics.IsPromotableTo(candidateType, formalType));
 
            if (TypeSemantics.IsCollectionType(candidateType) && TypeSemantics.IsCollectionType(formalType))
            { 
                return GetPromotionRank(TypeHelpers.GetElementTypeUsage(candidateType), TypeHelpers.GetElementTypeUsage(formalType)); 
            }
 
            PrimitiveType primitiveCandidateType = candidateType.EdmType as PrimitiveType;
            PrimitiveType primitiveFormalType = formalType.EdmType as PrimitiveType;
            if (null != primitiveCandidateType && null != primitiveFormalType)
            { 
                IList promotionTypes = EdmProviderManifest.Instance.GetPromotionTypes(primitiveCandidateType);
                if (primitiveCandidateType == primitiveFormalType) 
                { 
                    // we don't put the same type in the manifest, so we need to check
                    // if it is the same type. 
                    promotionRank = promotionTypes.Count + 1; // +1 because we want to be 1 above the rank of any other possibility
                }
                else
                { 
                    Debug.Assert(promotionTypes.Count > 0);
                    Debug.Assert(Helper.IsPromotableTo(promotionTypes, primitiveFormalType) != -1); 
                    promotionRank = promotionTypes.Count - Helper.IsPromotableTo(promotionTypes, primitiveFormalType); 
                }
            } 

            Debug.Assert(promotionRank >= 0, "promotionRank >=0");
            return promotionRank;
        } 

        ///  
        /// Try get fqtn from current metadata typespace 
        /// 
        ///  
        /// 
        /// 
        internal bool TryGetTypeFromMetadata( string typeFullName, out TypeUsage typeUsage )
        { 
            return _perspective.TryGetTypeByName(typeFullName, true /* ignore case */, out typeUsage);
        } 
 

        ///  
        /// Returns the proper TypeUsage for a given literal expression
        /// 
        /// 
        ///  
        internal TypeUsage GetLiteralTypeUsage( Literal literal )
        { 
            PrimitiveType primitiveType = null; 

            if (!ClrProviderManifest.Instance.TryGetPrimitiveType(literal.Type, out primitiveType)) 
            {
                throw EntityUtil.EntitySqlError(literal.ErrCtx, System.Data.Entity.Strings.LiteralTypeNotFoundInMetadata(literal.OriginalValue));
            }
            TypeUsage literalTypeUsage = TypeHelpers.GetLiteralTypeUsage(primitiveType.PrimitiveTypeKind, literal.IsUnicodeString); 

            return literalTypeUsage; 
        } 

        ///  
        /// Trims prefix from fqn in array form
        /// 
        /// 
        ///  
        /// 
        internal static string[] TrimNamesPrefix( string[] names, int startIndex ) 
        { 
            string[] s = new string[names.Length - 1];
            for (int i = startIndex ; i < names.Length ; s[i - 1] = names[i], i++) ; 
            return s;
        }

        ///  
        /// returns full string
        ///  
        ///  
        /// 
        static internal string GetFullName( string[] names ) 
        {
            return ConcatStringsWithSeparator(names, '.', 0 /*startIndex*/, names.Length);
        }
 
        static private string ConcatStringsWithSeparator( string[] names, char separator, int startIndex, int endIndex )
        { 
            Debug.Assert(names.Length > 0, "names.Length > 0"); 
            Debug.Assert(startIndex <= endIndex, "startIndex <= endIndex");
            Debug.Assert(startIndex >= 0, "startIndex >= 0"); 
            Debug.Assert(startIndex < names.Length, "startIndex < names.Length");

            if (startIndex == endIndex)
            { 
                return names[startIndex];
            } 
 
            StringBuilder sb = new StringBuilder();
            sb.Append(names[startIndex]); 
            for (int i = startIndex + 1 ; i < endIndex ; i++)
            {
                sb.Append(separator).Append(names[i]);
            } 
            return sb.ToString();
        } 
    } 

} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backup [....] 
//--------------------------------------------------------------------- 

 
namespace System.Data.Common.EntitySql
{
    using System;
    using System.Globalization; 
    using System.Collections.Generic;
    using System.Text; 
    using System.Diagnostics; 
    using System.Data.Common;
    using System.Data.Metadata.Edm; 
    using System.Data.Entity;

    /// 
    /// Represents Type Resolver Helper in the context of a typespace 
    /// 
    internal sealed class TypeResolver 
    { 
        private TypeUsage _cachedStringType;
        private TypeUsage _cachedBooleanType; 
        private TypeUsage _cachedInt64Type;
        private Perspective _perspective;
        private Dictionary _aliasedNamespaces;
        private HashSet _namespaces; 

        ///  
        /// Initializes TypeResolver instance 
        /// 
        ///  
        /// 
        internal TypeResolver( Perspective perspective, StringComparer stringComparer )
        {
            EntityUtil.CheckArgumentNull(perspective, "perspective"); 

            _perspective = perspective; 
 
            _aliasedNamespaces = new Dictionary(stringComparer);
 
            _namespaces = new HashSet(stringComparer);
        }

        ///  
        /// returns perspective instance
        ///  
        internal Perspective Perspective 
        {
            get { return _perspective; } 
        }

        /// 
        /// Add aliased namespace declaration 
        /// 
        ///  
        ///  
        internal bool TryAddAliasedNamespace( string alias, string namespaceName )
        { 
            if (_aliasedNamespaces.ContainsKey(alias))
            {
                return false;
            } 

            _aliasedNamespaces.Add(alias, namespaceName); 
 
            return true;
        } 


        /// 
        /// Add namespaces declaration 
        /// 
        ///  
        internal bool TryAddNamespace( string namespaceName ) 
        {
            if (_namespaces.Contains(namespaceName)) 
            {
                return false;
            }
 
            _namespaces.Add(namespaceName);
 
            return true; 
        }
 
        /// 
        /// returns true if key type is valid for collation
        /// 
        ///  
        /// 
        internal static bool IsKeyValidForCollation( TypeUsage type ) 
        { 
            return (TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.String) /* && isSearchable */ );
        } 

        /// 
        /// returns if a given type is allowed to have method calls
        ///  
        /// 
        ///  
        internal static bool IsValidTypeForMethodCall( TypeUsage type ) 
        {
            return (type.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType); 
        }

        /// 
        /// returns true if type is string type 
        /// 
        ///  
        ///  
        internal static bool IsStringType( TypeUsage type )
        { 
            return TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.String);
        }

        ///  
        /// Checks if a type is boolean
        ///  
        ///  
        /// 
        internal static bool IsBooleanType( TypeUsage type ) 
        {
            return TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.Boolean);
        }
 
        /// 
        /// Checks if two types are sub/super type inclusive 
        ///  
        /// 
        ///  
        /// 
        internal static bool IsSubOrSuperType( TypeUsage type1, TypeUsage type2 )
        {
            return TypeSemantics.IsEquivalent(type1, type2) || type1.IsSubtypeOf(type2) || type2.IsSubtypeOf(type1); 
        }
 
        ///  
        /// returns target space Edm.String type
        ///  
        internal TypeUsage StringType
        {
            get
            { 
                if (null == _cachedStringType)
                { 
                    _cachedStringType = _perspective.MetadataWorkspace.GetCanonicalModelTypeUsage(PrimitiveTypeKind.String); 
                }
                return _cachedStringType; 
            }
        }

        ///  
        /// returns target space Edm.Booelan type
        ///  
        internal TypeUsage BooleanType 
        {
            get 
            {
                if (null == _cachedBooleanType)
                {
                    _cachedBooleanType = _perspective.MetadataWorkspace.GetCanonicalModelTypeUsage(PrimitiveTypeKind.Boolean); 
                }
                return _cachedBooleanType; 
            } 
        }
 
        /// 
        /// returns target space Edm.Int64 type
        /// 
        internal TypeUsage Int64Type 
        {
            get 
            { 
                if (null == _cachedInt64Type)
                { 
                    _cachedInt64Type = _perspective.MetadataWorkspace.GetCanonicalModelTypeUsage(PrimitiveTypeKind.Int64);
                }
                return _cachedInt64Type;
            } 
        }
 
        ///  
        /// resolves a name as type
        ///  
        /// 
        /// 
        /// 
        /// TypeUsage 
        internal TypeUsage ResolveNameAsType( string[] names, int countNames, out int matchCount )
        { 
            TypeUsage TypeUsage = null; 
            matchCount = 0;
 
            //
            // lookup type in aliased namespaces if aliased
            //
            if (names.Length > 1 && (countNames > (names.Length - 1))) 
            {
                string namespaceName = null; 
                if (_aliasedNamespaces.TryGetValue(names[0], out namespaceName)) 
                {
                    if (TryGetTypeFromMetadata(namespaceName + "." + ConcatStringsWithSeparator(names, '.', 1, countNames - 1), out TypeUsage)) 
                    {
                        matchCount = 1;
                        return TypeUsage;
                    } 
                }
            } 
 
            string typeName = ConcatStringsWithSeparator(names, '.', 0, countNames);
 
            //
            // Try Full type name
            //
            if (TryGetTypeFromMetadata(typeName, out TypeUsage)) 
            {
                matchCount = 1; 
                return TypeUsage; 
            }
 
            //
            // lookup type in namespaces
            //
            TypeUsage matchType; 
            foreach (string ns in _namespaces)
            { 
                if (TryGetTypeFromMetadata(ns + "." + typeName, out matchType)) 
                {
                    matchCount++; 
                    TypeUsage = matchType;
                }
            }
 
            return TypeUsage;
        } 
 
        /// 
        /// Resolves a Name as Function 
        /// 
        /// 
        /// 
        ///  
        /// 
        ///  
        internal IList ResolveNameAsFunction( string[] names, bool ignoreCase, out int matchCount, 
            out List foundNamespaces)
        { 
            IList functionList = null;
            foundNamespaces = new List();
            string namespaceName = null;
            string functionName = names[names.Length - 1]; 
            matchCount = 0;
 
            // 
            // lookup type in aliased namespaces if aliased
            // 
            if (names.Length > 1)
            {
                if (_aliasedNamespaces.TryGetValue(names[0], out namespaceName))
                { 
                    if (TryGetFunctionFromMetadata(functionName, namespaceName, ignoreCase, out functionList))
                    { 
                        matchCount = 1; 
                        foundNamespaces.Add(namespaceName);
                        return functionList; 
                    }
                }

                // 
                // Try function full name
                // 
                namespaceName = ConcatStringsWithSeparator(names, '.', 0, names.Length - 1); 
                if (TryGetFunctionFromMetadata(functionName, namespaceName, ignoreCase, out functionList))
                { 
                    matchCount = 1;
                    foundNamespaces.Add(namespaceName);
                }
 
                return functionList;
            } 
 
            //
            // lookup type in namespaces 
            //
            IList tmpFunctionList;
            foreach (string ns in _namespaces)
            { 
                if (TryGetFunctionFromMetadata(functionName, ns, ignoreCase, out tmpFunctionList))
                { 
                    matchCount++; 
                    functionList = tmpFunctionList;
                    foundNamespaces.Add(ns); 
                }
            }

            return functionList; 
        }
 
        ///  
        /// find name base type
        ///  
        /// 
        /// 
        /// 
        ///  
        internal TypeUsage ResolveBaseType( string[] names, out int suffixIndex, out int matchCount )
        { 
            TypeUsage TypeUsage = null; 
            suffixIndex = 0;
            matchCount = 0; 

            Debug.Assert(names.Length > 0, "names.Length > 0");

            // 
            // lookup in aliased namespaces
            // 
            if (!TryGetBaseTypeInAliasedNamespaces(names, out TypeUsage, out suffixIndex)) 
            {
 
                //
                // Try Resolve id base type
                //
                int idMatchCount = 0; 
                int idSuffix = 0;
                TypeUsage idTypeUsage; 
                if (TryGetIdentifierBaseType(names, out idTypeUsage, out idSuffix)) 
                {
                    idMatchCount++; 
                }

                //
                // lookup in known namespaces 
                //
                if (TryGetBaseTypeInNamespaces(names, out TypeUsage, out suffixIndex, out matchCount)) 
                { 
                    matchCount += idMatchCount;
                } 

                if (null == TypeUsage)
                {
                    TypeUsage = idTypeUsage; 
                    suffixIndex = idSuffix;
                    matchCount = idMatchCount; 
                } 

            } 

            return TypeUsage;
        }
 
        /// 
        /// given an identifier try to get its base type 
        ///  
        /// 
        ///  
        /// 
        /// 
        internal bool TryGetIdentifierBaseType( string[] names, out TypeUsage TypeUsage, out int suffixIndex )
        { 
            TypeUsage = null;
            suffixIndex = 0; 
            System.Text.StringBuilder sb = new System.Text.StringBuilder(); 
            for(int i=0; i < names.Length; i++)
            { 
                sb.Append(names[i]);
                if (TryGetTypeFromMetadata(sb.ToString(), out TypeUsage))
                {
                    suffixIndex = i; 
                    return true;
                } 
                sb.Append('.'); 
            }
            return false; 
        }


        ///  
        /// try resolve base type in aliased namespaces
        ///  
        ///  
        /// 
        ///  
        /// 
        internal bool TryGetBaseTypeInAliasedNamespaces( string[] names, out TypeUsage TypeUsage, out int suffixIndex )
        {
            TypeUsage = null; 
            suffixIndex = 0;
 
            if (names.Length > 1) 
            {
                string namespaceName = null; 
                if (_aliasedNamespaces.TryGetValue(names[0], out namespaceName))
                {
                    if (TryGetBaseTypeFromMetadata(namespaceName, TrimNamesPrefix(names, 1), out TypeUsage, out suffixIndex))
                    { 
                        suffixIndex++;
                        return true; 
                    } 
                }
            } 

            return false;
        }
 

        ///  
        /// try resolve Base type in declared non-aliased namespaces 
        /// 
        ///  
        /// 
        /// 
        /// 
        ///  
        internal bool TryGetBaseTypeInNamespaces( string[] names, out TypeUsage TypeUsage, out int suffixIndex, out int matchCount )
        { 
            TypeUsage = null; 
            suffixIndex = 0;
            matchCount = 0; 
            TypeUsage matchType = null;

            foreach (string nsPrefix in _namespaces)
            { 
                if (TryGetTypeFromMetadata(nsPrefix + "." + names[0], out TypeUsage))
                { 
                    matchType = TypeUsage; 
                    suffixIndex = 1;
                    matchCount++; 
                }
            }

            TypeUsage = matchType; 
            return (matchCount > 0);
        } 
 

        ///  
        /// try get base type from metadata
        /// 
        /// 
        ///  
        /// 
        ///  
        ///  
        internal bool TryGetBaseTypeFromMetadata( string namespaceName, string[] names, out TypeUsage TypeUsage, out int suffixIndex )
        { 
            TypeUsage = null;
            suffixIndex = 0;

            if (TryGetTypeFromMetadata(namespaceName + "." + names[0], out TypeUsage)) 
            {
                suffixIndex = 1; 
            } 

            return (null != TypeUsage); 
        }

        /// 
        /// Lookup metadata for a function given its fqn 
        /// 
        ///  
        ///  
        /// 
        ///  
        /// 
        internal bool TryGetFunctionFromMetadata(string name, string namespaceName, bool ignoreCase,
            out IList functionMetadata)
        { 
            System.Collections.ObjectModel.ReadOnlyCollection functions =
                _perspective.GetFunctions(name, namespaceName, ignoreCase); 
 
            functionMetadata = functions;
            if (functionMetadata.Count > 0) 
            {
                return true;
            }
            return false; 
        }
 
 
        /// 
        /// Get global function metadata 
        /// 
        /// 
        /// 
        ///  
        /// 
        /// Funciton metadata 
        internal static EdmFunction ResolveFunctionOverloads( IList functionsMetadata, 
                                                              IList argTypes,
                                                              bool isGroupAggregateFunction, 
                                                              out bool isAmbiguous )
        {
            EdmFunction closestFunctionMatch = null;
            uint maxRank = 0; 
            isAmbiguous = false;
 
            Debug.Assert(functionsMetadata.Count > 0, "functionsMetadata.Count must be greater than zero"); 

            for (int i = 0 ; i < functionsMetadata.Count ; i++) 
            {
                uint rank = RankFunctionParameters(argTypes,
                                                   functionsMetadata[i].Parameters,
                                                   isGroupAggregateFunction); 

                if (0 == rank) 
                { 
                    continue;
                } 

                if (rank == maxRank)
                {
                    isAmbiguous = true; 
                }
 
                if (rank > maxRank) 
                {
                    isAmbiguous = false; 
                    maxRank = rank;
                    closestFunctionMatch = functionsMetadata[i];
                }
            } 

            return closestFunctionMatch; 
        } 

 
        /// 
        /// Ranks a list of candidate parameter types against the function formal signature especification
        /// 
        /// list of candidate parameter types 
        /// function formal signature parameter metadata
        ///  
        ///  
        /// assumes no overload will have more than 10^12 equivalent parameters
        static internal uint RankFunctionParameters(  IList candidateParams, 
                                                      IList signatureParams,
                                                      bool isGroupAggregateFunction )
        {
            if (candidateParams.Count != signatureParams.Count) 
            {
                return 0; 
            } 

            if (0 == candidateParams.Count && 0 == signatureParams.Count) 
            {
                return 0X40000000;
            }
 
            int equivalenceCount = 0;
            int promotionCount = 0; 
            for (int i = 0 ; i < candidateParams.Count ; i++) 
            {
                TypeUsage candidateParamType = candidateParams[i]; 
                TypeUsage formalParamType = signatureParams[i].TypeUsage;
                //
                // if function being ranked is a group aggregate, consider the element type
                // 
                if (isGroupAggregateFunction)
                { 
                    if (!TypeSemantics.IsCollectionType(formalParamType)) 
                    {
                        // 
                        // even though it is the job of metadata to ensure that the provider manifest is consistent
                        // ensure that if a function is marked as aggregate, then the argument type must be of collection{GivenType}
                        //
                        throw EntityUtil.EntitySqlError(Strings.InvalidArgumentTypeForAggregateFunction); 
                    }
                    formalParamType = TypeHelpers.GetElementTypeUsage(formalParamType); 
                } 

                if (signatureParams[i].Mode != ParameterMode.In && signatureParams[i].Mode != ParameterMode.InOut) 
                {
                    return 0;
                }
 
                if (TypeSemantics.IsEquivalent(candidateParamType, formalParamType) ||
                   (TypeSemantics.IsNullType(candidateParamType) && !TypeSemantics.IsCollectionType(formalParamType))) 
                { 
                    equivalenceCount++;
                } 
                else if (TypeSemantics.IsPromotableTo(candidateParamType, formalParamType))
                {
                    promotionCount += GetPromotionRank(candidateParamType, formalParamType);
                } 
                else
                { 
                    return 0; 
                }
            } 

            if (equivalenceCount >= 0x8000 || promotionCount >= 0x8000)
            {
                throw EntityUtil.EntitySqlError(Strings.TooManyFunctionArguments); 
            }
 
            return (uint)((equivalenceCount << 15) | promotionCount); 
        }
 

        /// 
        /// Assume that candidateType *IS PROMOTABLE* to formalType
        ///  
        /// 
        ///  
        ///  
        static private int GetPromotionRank( TypeUsage candidateType, TypeUsage formalType )
        { 
            int promotionRank = 1;

            Debug.Assert(TypeSemantics.IsPromotableTo(candidateType, formalType));
 
            if (TypeSemantics.IsCollectionType(candidateType) && TypeSemantics.IsCollectionType(formalType))
            { 
                return GetPromotionRank(TypeHelpers.GetElementTypeUsage(candidateType), TypeHelpers.GetElementTypeUsage(formalType)); 
            }
 
            PrimitiveType primitiveCandidateType = candidateType.EdmType as PrimitiveType;
            PrimitiveType primitiveFormalType = formalType.EdmType as PrimitiveType;
            if (null != primitiveCandidateType && null != primitiveFormalType)
            { 
                IList promotionTypes = EdmProviderManifest.Instance.GetPromotionTypes(primitiveCandidateType);
                if (primitiveCandidateType == primitiveFormalType) 
                { 
                    // we don't put the same type in the manifest, so we need to check
                    // if it is the same type. 
                    promotionRank = promotionTypes.Count + 1; // +1 because we want to be 1 above the rank of any other possibility
                }
                else
                { 
                    Debug.Assert(promotionTypes.Count > 0);
                    Debug.Assert(Helper.IsPromotableTo(promotionTypes, primitiveFormalType) != -1); 
                    promotionRank = promotionTypes.Count - Helper.IsPromotableTo(promotionTypes, primitiveFormalType); 
                }
            } 

            Debug.Assert(promotionRank >= 0, "promotionRank >=0");
            return promotionRank;
        } 

        ///  
        /// Try get fqtn from current metadata typespace 
        /// 
        ///  
        /// 
        /// 
        internal bool TryGetTypeFromMetadata( string typeFullName, out TypeUsage typeUsage )
        { 
            return _perspective.TryGetTypeByName(typeFullName, true /* ignore case */, out typeUsage);
        } 
 

        ///  
        /// Returns the proper TypeUsage for a given literal expression
        /// 
        /// 
        ///  
        internal TypeUsage GetLiteralTypeUsage( Literal literal )
        { 
            PrimitiveType primitiveType = null; 

            if (!ClrProviderManifest.Instance.TryGetPrimitiveType(literal.Type, out primitiveType)) 
            {
                throw EntityUtil.EntitySqlError(literal.ErrCtx, System.Data.Entity.Strings.LiteralTypeNotFoundInMetadata(literal.OriginalValue));
            }
            TypeUsage literalTypeUsage = TypeHelpers.GetLiteralTypeUsage(primitiveType.PrimitiveTypeKind, literal.IsUnicodeString); 

            return literalTypeUsage; 
        } 

        ///  
        /// Trims prefix from fqn in array form
        /// 
        /// 
        ///  
        /// 
        internal static string[] TrimNamesPrefix( string[] names, int startIndex ) 
        { 
            string[] s = new string[names.Length - 1];
            for (int i = startIndex ; i < names.Length ; s[i - 1] = names[i], i++) ; 
            return s;
        }

        ///  
        /// returns full string
        ///  
        ///  
        /// 
        static internal string GetFullName( string[] names ) 
        {
            return ConcatStringsWithSeparator(names, '.', 0 /*startIndex*/, names.Length);
        }
 
        static private string ConcatStringsWithSeparator( string[] names, char separator, int startIndex, int endIndex )
        { 
            Debug.Assert(names.Length > 0, "names.Length > 0"); 
            Debug.Assert(startIndex <= endIndex, "startIndex <= endIndex");
            Debug.Assert(startIndex >= 0, "startIndex >= 0"); 
            Debug.Assert(startIndex < names.Length, "startIndex < names.Length");

            if (startIndex == endIndex)
            { 
                return names[startIndex];
            } 
 
            StringBuilder sb = new StringBuilder();
            sb.Append(names[startIndex]); 
            for (int i = startIndex + 1 ; i < endIndex ; i++)
            {
                sb.Append(separator).Append(names[i]);
            } 
            return sb.ToString();
        } 
    } 

} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK