Mono.CSharp.ImportedTypeDefinition.LoadMembers C# (CSharp) Method

LoadMembers() public method

public LoadMembers ( System.TypeSpec declaringType, bool onlyTypes, Mono.CSharp.MemberCache &cache ) : void
declaringType System.TypeSpec
onlyTypes bool
cache Mono.CSharp.MemberCache
return void
        public void LoadMembers(TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
        {
            //
            // Not interested in members of nested private types unless the importer needs them
            //
            if (declaringType.IsPrivate && importer.IgnorePrivateMembers) {
                cache = MemberCache.Empty;
                return;
            }

            var loading_type = (MetaType) provider;
            const BindingFlags all_members = BindingFlags.DeclaredOnly |
                BindingFlags.Static | BindingFlags.Instance |
                BindingFlags.Public | BindingFlags.NonPublic;

            const MethodAttributes explicit_impl = MethodAttributes.NewSlot |
                    MethodAttributes.Virtual | MethodAttributes.HideBySig |
                    MethodAttributes.Final;

            Dictionary<MethodBase, MethodSpec> possible_accessors = null;
            List<EventSpec> imported_events = null;
            EventSpec event_spec;
            MemberSpec imported;
            MethodInfo m;
            MemberInfo[] all;
            try {
                all = loading_type.GetMembers (all_members);
            } catch (Exception e) {
                throw new InternalErrorException (e, "Could not import type `{0}' from `{1}'",
                    declaringType.GetSignatureForError (), declaringType.MemberDefinition.DeclaringAssembly.FullName);
            }

            if (cache == null) {
                cache = new MemberCache (all.Length);

                //
                // Do the types first as they can be referenced by the members before
                // they are found or inflated
                //
                foreach (var member in all) {
                    if (member.MemberType != MemberTypes.NestedType)
                        continue;

                    var t = (MetaType) member;

                    // Ignore compiler generated types, mostly lambda containers
                    if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers)
                        continue;

                    imported = importer.CreateNestedType (t, declaringType);
                    cache.AddMemberImported (imported);
                }

                foreach (var member in all) {
                    if (member.MemberType != MemberTypes.NestedType)
                        continue;

                    var t = (MetaType) member;

                    if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers)
                        continue;

                    importer.ImportTypeBase (t);
                }
            }

            if (!onlyTypes) {
                //
                // The logic here requires methods to be returned first which seems to work for both Mono and .NET
                //
                foreach (var member in all) {
                    switch (member.MemberType) {
                    case MemberTypes.Constructor:
                    case MemberTypes.Method:
                        MethodBase mb = (MethodBase) member;
                        var attrs = mb.Attributes;

                        if ((attrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) {
                            if (importer.IgnorePrivateMembers)
                                continue;

                            // Ignore explicitly implemented members
                            if ((attrs & explicit_impl) == explicit_impl)
                                continue;

                            // Ignore compiler generated methods
                            if (importer.HasAttribute (CustomAttributeData.GetCustomAttributes (mb), "CompilerGeneratedAttribute", MetadataImporter.CompilerServicesNamespace))
                                continue;
                        }

                        imported = importer.CreateMethod (mb, declaringType);
                        if (imported.Kind == MemberKind.Method && !imported.IsGeneric) {
                            if (possible_accessors == null)
                                possible_accessors = new Dictionary<MethodBase, MethodSpec> (ReferenceEquality<MethodBase>.Default);

                            // There are no metadata rules for accessors, we have to consider any method as possible candidate
                            possible_accessors.Add (mb, (MethodSpec) imported);
                        }

                        break;
                    case MemberTypes.Property:
                        if (possible_accessors == null)
                            continue;

                        var p = (PropertyInfo) member;
                        //
                        // Links possible accessors with property
                        //
                        MethodSpec get, set;
                        m = p.GetGetMethod (true);
                        if (m == null || !possible_accessors.TryGetValue (m, out get))
                            get = null;

                        m = p.GetSetMethod (true);
                        if (m == null || !possible_accessors.TryGetValue (m, out set))
                            set = null;

                        // No accessors registered (e.g. explicit implementation)
                        if (get == null && set == null)
                            continue;

                        imported = importer.CreateProperty (p, declaringType, get, set);
                        if (imported == null)
                            continue;

                        break;
                    case MemberTypes.Event:
                        if (possible_accessors == null)
                            continue;

                        var e = (EventInfo) member;
                        //
                        // Links accessors with event
                        //
                        MethodSpec add, remove;
                        m = e.GetAddMethod (true);
                        if (m == null || !possible_accessors.TryGetValue (m, out add))
                            add = null;

                        m = e.GetRemoveMethod (true);
                        if (m == null || !possible_accessors.TryGetValue (m, out remove))
                            remove = null;

                        // Both accessors are required
                        if (add == null || remove == null)
                            continue;

                        event_spec = importer.CreateEvent (e, declaringType, add, remove);
                        if (!importer.IgnorePrivateMembers) {
                            if (imported_events == null)
                                imported_events = new List<EventSpec> ();

                            imported_events.Add (event_spec);
                        }

                        imported = event_spec;
                        break;
                    case MemberTypes.Field:
                        var fi = (FieldInfo) member;

                        imported = importer.CreateField (fi, declaringType);
                        if (imported == null)
                            continue;

                        //
                        // For dynamic binder event has to be fully restored to allow operations
                        // within the type container to work correctly
                        //
                        if (imported_events != null) {
                            // The backing event field should be private but it may not
                            int i;
                            for (i = 0; i < imported_events.Count; ++i) {
                                var ev = imported_events[i];
                                if (ev.Name == fi.Name) {
                                    ev.BackingField = (FieldSpec) imported;
                                    imported_events.RemoveAt (i);
                                    i = -1;
                                    break;
                                }
                            }

                            if (i < 0)
                                continue;
                        }

                        break;
                    case MemberTypes.NestedType:
                        // Already in the cache from the first pass
                        continue;
                    default:
                        throw new NotImplementedException (member.ToString ());
                    }

                    cache.AddMemberImported (imported);
                }
            }

            if (declaringType.IsInterface && declaringType.Interfaces != null) {
                foreach (var iface in declaringType.Interfaces) {
                    cache.AddInterface (iface);
                }
            }
        }