internal ClassInfo(Type t) { members = new Hashtable(); indexer = null; }
internal ClassBase(Type tp) { indexer = null; type = tp; }
private static ClassInfo GetClassInfo(Type type) { var ci = new ClassInfo(type); var methods = new Hashtable(); ArrayList list; MethodInfo meth; ManagedType ob; string name; object item; Type tp; int i, n; // This is complicated because inheritance in Python is name // based. We can't just find DeclaredOnly members, because we // could have a base class A that defines two overloads of a // method and a class B that defines two more. The name-based // descriptor Python will find needs to know about inherited // overloads as well as those declared on the sub class. BindingFlags flags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; MemberInfo[] info = type.GetMembers(flags); var local = new Hashtable(); var items = new ArrayList(); MemberInfo m; // Loop through once to find out which names are declared for (i = 0; i < info.Length; i++) { m = info[i]; if (m.DeclaringType == type) { local[m.Name] = 1; } } // Now again to filter w/o losing overloaded member info for (i = 0; i < info.Length; i++) { m = info[i]; if (local[m.Name] != null) { items.Add(m); } } if (type.IsInterface) { // Interface inheritance seems to be a different animal: // more contractual, less structural. Thus, a Type that // represents an interface that inherits from another // interface does not return the inherited interface's // methods in GetMembers. For example ICollection inherits // from IEnumerable, but ICollection's GetMemebers does not // return GetEnumerator. // // Not sure if this is the correct way to fix this, but it // seems to work. Thanks to Bruce Dodson for the fix. Type[] inheritedInterfaces = type.GetInterfaces(); for (i = 0; i < inheritedInterfaces.Length; ++i) { Type inheritedType = inheritedInterfaces[i]; MemberInfo[] imembers = inheritedType.GetMembers(flags); for (n = 0; n < imembers.Length; n++) { m = imembers[n]; if (local[m.Name] == null) { items.Add(m); } } } } for (i = 0; i < items.Count; i++) { var mi = (MemberInfo)items[i]; switch (mi.MemberType) { case MemberTypes.Method: meth = (MethodInfo)mi; if (!(meth.IsPublic || meth.IsFamily || meth.IsFamilyOrAssembly)) { continue; } name = meth.Name; item = methods[name]; if (item == null) { item = methods[name] = new ArrayList(); } list = (ArrayList)item; list.Add(meth); continue; case MemberTypes.Property: var pi = (PropertyInfo)mi; MethodInfo mm = null; try { mm = pi.GetGetMethod(true); if (mm == null) { mm = pi.GetSetMethod(true); } } catch (SecurityException) { // GetGetMethod may try to get a method protected by // StrongNameIdentityPermission - effectively private. continue; } if (mm == null) { continue; } if (!(mm.IsPublic || mm.IsFamily || mm.IsFamilyOrAssembly)) { continue; } // Check for indexer ParameterInfo[] args = pi.GetIndexParameters(); if (args.GetLength(0) > 0) { Indexer idx = ci.indexer; if (idx == null) { ci.indexer = new Indexer(); idx = ci.indexer; } idx.AddProperty(pi); continue; } ob = new PropertyObject(pi); ci.members[pi.Name] = ob; continue; case MemberTypes.Field: var fi = (FieldInfo)mi; if (!(fi.IsPublic || fi.IsFamily || fi.IsFamilyOrAssembly)) { continue; } ob = new FieldObject(fi); ci.members[mi.Name] = ob; continue; case MemberTypes.Event: var ei = (EventInfo)mi; MethodInfo me = ei.GetAddMethod(true); if (!(me.IsPublic || me.IsFamily || me.IsFamilyOrAssembly)) { continue; } ob = new EventObject(ei); ci.members[ei.Name] = ob; continue; case MemberTypes.NestedType: tp = (Type)mi; if (!(tp.IsNestedPublic || tp.IsNestedFamily || tp.IsNestedFamORAssem)) { continue; } // Note the given instance might be uninitialized ob = GetClass(tp); ci.members[mi.Name] = ob; continue; } } IDictionaryEnumerator iter = methods.GetEnumerator(); while (iter.MoveNext()) { name = (string)iter.Key; list = (ArrayList)iter.Value; var mlist = (MethodInfo[])list.ToArray(typeof(MethodInfo)); ob = new MethodObject(type, name, mlist); ci.members[name] = ob; } return(ci); }