Microsoft.CSharp.RuntimeBinder.RuntimeBinder.CreateMemberGroupEXPR C# (CSharp) Method

CreateMemberGroupEXPR() private method

private CreateMemberGroupEXPR ( string Name, IList typeArguments, EXPR callingObject, SYMKIND kind ) : Microsoft.CSharp.RuntimeBinder.Semantics.EXPRMEMGRP
Name string
typeArguments IList
callingObject Microsoft.CSharp.RuntimeBinder.Semantics.EXPR
kind SYMKIND
return Microsoft.CSharp.RuntimeBinder.Semantics.EXPRMEMGRP
        private EXPRMEMGRP CreateMemberGroupEXPR(
            string Name,
            IList<Type> typeArguments,
            EXPR callingObject,
            SYMKIND kind)
        {
            Name name = SymbolTable.GetName(Name, _semanticChecker.GetNameManager());
            AggregateType callingType;

            if (callingObject.type.IsArrayType())
            {
                callingType = _semanticChecker.GetSymbolLoader().GetReqPredefType(PredefinedType.PT_ARRAY);
            }
            else if (callingObject.type.IsNullableType())
            {
                callingType = callingObject.type.AsNullableType().GetAts(_semanticChecker.GetSymbolLoader().GetErrorContext());
            }
            else if (callingObject.type.IsAggregateType())
            {
                callingType = callingObject.type.AsAggregateType();
            }
            else
            {
                callingType = null;
                Debug.Assert(false, "MemberGroup on non-array, non-aggregate");
            }

            List<CType> callingTypes = new List<CType>();

            // The C# binder expects that only the base virtual method is inserted
            // into the list of candidates, and only the type containing the base
            // virtual method is inserted into the list of types. However, since we
            // don't want to do all the logic, we're just going to insert every type
            // that has a member of the given name, and allow the C# binder to filter
            // out all overrides.
            //
            // Find that set of types now.
            symbmask_t mask = symbmask_t.MASK_MethodSymbol;
            switch (kind)
            {
                case SYMKIND.SK_PropertySymbol:
                case SYMKIND.SK_IndexerSymbol:
                    mask = symbmask_t.MASK_PropertySymbol;
                    break;
                case SYMKIND.SK_MethodSymbol:
                    mask = symbmask_t.MASK_MethodSymbol;
                    break;
                default:
                    Debug.Assert(false, "Unhandled kind");
                    break;
            }

            // If we have a constructor, only find its type.
            bool bIsConstructor = name == SymbolLoader.GetNameManager().GetPredefinedName(PredefinedName.PN_CTOR);
            for (AggregateType t = callingType; t != null; t = t.GetBaseClass())
            {
                if (_symbolTable.AggregateContainsMethod(t.GetOwningAggregate(), Name, mask))
                {
                    callingTypes.Add(t);
                }

                // If we have a constructor, run the loop once for the constructor's type, and thats it.
                if (bIsConstructor)
                {
                    break;
                }
            }

            // If this is a WinRT type we have to add all collection interfaces that have this method 
            // as well so that overload resolution can find them.
            if (callingType.IsWindowsRuntimeType())
            {
                TypeArray collectioniFaces = callingType.GetWinRTCollectionIfacesAll(SymbolLoader);

                for (int i = 0; i < collectioniFaces.size; i++)
                {
                    CType t = collectioniFaces.Item(i);
                    // Collection interfaces will be aggregates.
                    Debug.Assert(t.IsAggregateType());

                    if (_symbolTable.AggregateContainsMethod(t.AsAggregateType().GetOwningAggregate(), Name, mask))
                    {
                        callingTypes.Add(t);
                    }
                }
            }

            EXPRFLAG flags = EXPRFLAG.EXF_USERCALLABLE;
            // If its a delegate, mark that on the memgroup.
            if (Name == SpecialNames.Invoke && callingObject.type.isDelegateType())
            {
                flags |= EXPRFLAG.EXF_DELEGATE;
            }

            // For a constructor, we need to seed the memgroup with the constructor flag.
            if (Name == SpecialNames.Constructor)
            {
                flags |= EXPRFLAG.EXF_CTOR;
            }

            // If we have an indexer, mark that.
            if (Name == SpecialNames.Indexer)
            {
                flags |= EXPRFLAG.EXF_INDEXER;
            }

            TypeArray typeArgumentsAsTypeArray = BSYMMGR.EmptyTypeArray();
            if (typeArguments != null && typeArguments.Count > 0)
            {
                typeArgumentsAsTypeArray = _semanticChecker.getBSymmgr().AllocParams(
                    _symbolTable.GetCTypeArrayFromTypes(typeArguments));
            }
            EXPRMEMGRP memgroup = _exprFactory.CreateMemGroup(// Tree
                flags, name, typeArgumentsAsTypeArray, kind, callingType, null, null, new CMemberLookupResults(
                    _semanticChecker.getBSymmgr().AllocParams(callingTypes.Count, callingTypes.ToArray()),
                    name));
            if (callingObject.isCLASS())
            {
                memgroup.SetOptionalLHS(callingObject);
            }
            else
            {
                memgroup.SetOptionalObject(callingObject);
            }
            return memgroup;
        }