/// <summary> /// This function tells whether one of our base classes implements /// the given method (which turns out, it is valid to have an interface /// implementation in a base /// </summary> bool BaseImplements(Type iface_type, MethodInfo mi, out MethodInfo base_method) { MethodSignature ms; AParametersCollection param = TypeManager.GetParameterData(mi); ms = new MethodSignature(mi.Name, TypeManager.TypeToCoreType(mi.ReturnType), param.Types); MemberList list = TypeContainer.FindMembers( container.TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, MethodSignature.method_signature_filter, ms); if (list.Count == 0) { base_method = null; return(false); } if (TypeManager.ImplementsInterface(container.TypeBuilder.BaseType, iface_type)) { base_method = null; return(true); } base_method = (MethodInfo)list [0]; if (base_method.DeclaringType.IsInterface) { return(false); } if (!base_method.IsPublic) { return(false); } if (!base_method.IsAbstract && !base_method.IsVirtual) { // FIXME: We can avoid creating a proxy if base_method can be marked 'final virtual' instead. // However, it's too late now, the MethodBuilder has already been created (see bug 377519) DefineProxy(iface_type, base_method, mi, param); } return(true); }
// <remarks> // Returns a list of the abstract methods that are exposed by all of our // bases that we must implement. Notice that this `flattens' the // method search space, and takes into account overrides. // </remarks> static ArrayList GetAbstractMethods(Type t) { ArrayList list = null; bool searching = true; Type current_type = t; do { MemberList mi; mi = TypeContainer.FindMembers( current_type, MemberTypes.Method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, virtual_method_filter, null); if (current_type == TypeManager.object_type) { searching = false; } else { current_type = current_type.BaseType; if (!current_type.IsAbstract) { searching = false; } } if (mi.Count == 0) { continue; } if (mi.Count == 1 && !(mi [0] is MethodBase)) { searching = false; } else { list = TypeManager.CopyNewMethods(list, mi); } } while (searching); if (list == null) { return(null); } for (int i = 0; i < list.Count; i++) { while (list.Count > i && !((MethodInfo)list [i]).IsAbstract) { list.RemoveAt(i); } } if (list.Count == 0) { return(null); } return(list); }