IronRuby.Runtime.Calls.MemberGroupBuilder.TryGetClrMethod C# (CSharp) Method

TryGetClrMethod() private method

There are basically 4 cases: 1) CLR method of the given name is not defined in the specified type. Do nothing, the method will be found as we traverse the hierarhy towards the Kernel module. 2) Otherwise 1) There is no RubyMemberInfo of given name present in the (type..Kernel] ancestors. We need to search all types in (type..Object] for CLR method overloads. 2) There is a RubyMemberInfo in a class, say C, in (type..Kernel]. We need to get CLR methods from (type..C) in addition to the members in the type. 1) C.HidesInheritedOverloads == true All overloads of the method we look for are in [type..C). 2) C.HidesInheritedOverloads == false All overloads of the method we look for are in [type..C) and in the RubyMemberInfo.
private TryGetClrMethod ( RubyClass cls, Type type, BindingFlags bindingFlags, string name, string clrName, IronRuby.Runtime.Calls.RubyMemberInfo &method ) : bool
cls IronRuby.Builtins.RubyClass
type System.Type
bindingFlags BindingFlags
name string
clrName string
method IronRuby.Runtime.Calls.RubyMemberInfo
return bool
        internal bool TryGetClrMethod(RubyClass/*!*/ cls, Type/*!*/ type, BindingFlags bindingFlags, string/*!*/ name, string/*!*/ clrName, out RubyMemberInfo method) {

            // declared only:
            MemberInfo[] initialMembers = GetDeclaredClrMethods(type, bindingFlags, clrName);
            int initialVisibleMemberCount = GetVisibleMethodCount(initialMembers);
            if (initialVisibleMemberCount == 0) {
                // case [1]
                method = null;
                return false;
            }

            // inherited overloads:
            List<RubyClass> ancestors = new List<RubyClass>();
            RubyMemberInfo inheritedRubyMember = null;
            bool skipHidden = false;

            cls.ForEachAncestor((module) => {
                if (module != cls) {
                    if (module.TryGetDefinedMethod(name, ref skipHidden, out inheritedRubyMember) && !inheritedRubyMember.IsSuperForwarder) {
                        return true;
                    }

                    // Skip classes that have no tracker, e.g. Fixnum(tracker) <: Integer(null) <: Numeric(null) <: Object(tracker).
                    // Skip interfaces, their methods are not callable => do not include them into a method group.
                    // Skip all classes once hidden sentinel is encountered (no CLR overloads are visible since then).
                    if (!skipHidden && module.TypeTracker != null && module.IsClass) {
                        ancestors.Add((RubyClass)module);
                    }
                }

                // continue:
                return false;
            });

            _allMethods = null;
            if (inheritedRubyMember != null) {
                // case [2.2.2]: add CLR methods from the Ruby member:
                var inheritedGroup = inheritedRubyMember as RubyMethodGroupInfo;
                if (inheritedGroup != null) {
                    AddMethodsOverwriteExisting(inheritedGroup.MethodBases, inheritedGroup.OverloadOwners);
                }
            }

            // populate classes in (type..Kernel] or (type..C) with method groups:
            for (int i = ancestors.Count - 1; i >= 0; i--) {
                var declared = GetDeclaredClrMethods(ancestors[i].TypeTracker.Type, bindingFlags, clrName);
                if (declared.Length != 0 && AddMethodsOverwriteExisting(declared, null)) {
                    // There is no cached method that needs to be invalidated.
                    //
                    // Proof:
                    // Suppose the group being created here overridden an existing method that is cached in a dynamic site invoked on some target class.
                    // Then either the target class is above all ancestors[i] or below some. If it is above then the new group doesn't 
                    // invalidate validity of the site. If it is below then the method resolution for the cached method would create
                    // and store to method tables all method groups in between the target class and the owner of the cached method, including the 
                    // one that contain overloads of ancestors[i]. But no module below inheritedRubyMember contains a method group of the name 
                    // being currently resolved.
                    ancestors[i].AddMethodNoCacheInvalidation(name, MakeAllMethodsGroup(ancestors[i]));
                }
            }

            if (_allMethods != null) {
                // add members declared in self:
                AddMethodsOverwriteExisting(initialMembers, null);

                // return the group, it will be stored in the method table by the caller:
                method = MakeAllMethodsGroup(cls);
            } else {
                method = MakeSingleOwnerGroup(cls, initialMembers, initialVisibleMemberCount);
            }

            return true;
        }