예제 #1
0
        internal static Symbol GetRuntimeMember(NamedTypeSymbol declaringType, ref MemberDescriptor descriptor, SignatureComparer <MethodSymbol, FieldSymbol, PropertySymbol, TypeSymbol, ParameterSymbol> comparer, AssemblySymbol accessWithinOpt)
        {
            Symbol     result = null;
            SymbolKind targetSymbolKind;
            MethodKind targetMethodKind = MethodKind.Ordinary;
            bool       isStatic         = (descriptor.Flags & MemberFlags.Static) != 0;

            switch (descriptor.Flags & MemberFlags.KindMask)
            {
            case MemberFlags.Constructor:
                targetSymbolKind = SymbolKind.Method;
                targetMethodKind = MethodKind.Constructor;
                //  static constructors are never called explicitly
                Debug.Assert(!isStatic);
                break;

            case MemberFlags.Method:
                targetSymbolKind = SymbolKind.Method;
                break;

            case MemberFlags.PropertyGet:
                targetSymbolKind = SymbolKind.Method;
                targetMethodKind = MethodKind.PropertyGet;
                break;

            case MemberFlags.Field:
                targetSymbolKind = SymbolKind.Field;
                break;

            case MemberFlags.Property:
                targetSymbolKind = SymbolKind.Property;
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(descriptor.Flags);
            }

            foreach (var member in declaringType.GetMembers(descriptor.Name))
            {
                Debug.Assert(member.Name.Equals(descriptor.Name));

                if (member.Kind != targetSymbolKind || member.IsStatic != isStatic ||
                    !(member.DeclaredAccessibility == Accessibility.Public || ((object)accessWithinOpt != null && Symbol.IsSymbolAccessible(member, accessWithinOpt))))
                {
                    continue;
                }

                switch (targetSymbolKind)
                {
                case SymbolKind.Method:
                {
                    MethodSymbol method     = (MethodSymbol)member;
                    MethodKind   methodKind = method.MethodKind;
                    // Treat user-defined conversions and operators as ordinary methods for the purpose
                    // of matching them here.
                    if (methodKind == MethodKind.Conversion || methodKind == MethodKind.UserDefinedOperator)
                    {
                        methodKind = MethodKind.Ordinary;
                    }

                    if (method.Arity != descriptor.Arity || methodKind != targetMethodKind ||
                        ((descriptor.Flags & MemberFlags.Virtual) != 0) != (method.IsVirtual || method.IsOverride || method.IsAbstract))
                    {
                        continue;
                    }

                    if (!comparer.MatchMethodSignature(method, descriptor.Signature))
                    {
                        continue;
                    }
                }

                break;

                case SymbolKind.Property:
                {
                    PropertySymbol property = (PropertySymbol)member;
                    if (((descriptor.Flags & MemberFlags.Virtual) != 0) != (property.IsVirtual || property.IsOverride || property.IsAbstract))
                    {
                        continue;
                    }

                    if (!comparer.MatchPropertySignature(property, descriptor.Signature))
                    {
                        continue;
                    }
                }

                break;

                case SymbolKind.Field:
                    if (!comparer.MatchFieldSignature((FieldSymbol)member, descriptor.Signature))
                    {
                        continue;
                    }

                    break;

                default:
                    throw ExceptionUtilities.UnexpectedValue(targetSymbolKind);
                }

                // ambiguity
                if ((object)result != null)
                {
                    result = null;
                    break;
                }

                result = member;
            }
            return(result);
        }