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 && meta_import.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) continue; imported = meta_import.CreateNestedType (t, declaringType); cache.AddMember (imported); } foreach (var member in all) { if (member.MemberType != MemberTypes.NestedType) continue; var t = (MetaType) member; if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate) continue; meta_import.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 (meta_import.IgnorePrivateMembers) continue; // Ignore explicitly implemented members if ((attrs & explicit_impl) == explicit_impl) continue; // Ignore compiler generated methods if (MetadataImporter.HasAttribute (CustomAttributeData.GetCustomAttributes (mb), "CompilerGeneratedAttribute", MetadataImporter.CompilerServicesNamespace)) continue; } imported = meta_import.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 = meta_import.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 = meta_import.CreateEvent (e, declaringType, add, remove); if (!meta_import.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 = meta_import.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 index = imported_events.FindIndex (l => l.Name == fi.Name); if (index >= 0) { event_spec = imported_events[index]; event_spec.BackingField = (FieldSpec) imported; imported_events.RemoveAt (index); continue; } } break; case MemberTypes.NestedType: // Already in the cache from the first pass continue; default: throw new NotImplementedException (member.ToString ()); } cache.AddMember (imported); } } if (declaringType.IsInterface && declaringType.Interfaces != null) { foreach (var iface in declaringType.Interfaces) { cache.AddInterface (iface); } } }
public override bool Define () { if (IsGeneric) { foreach (TypeParameter type_param in TypeParameters) { if (!type_param.Resolve (this)) return false; } foreach (TypeParameter type_param in TypeParameters) { if (!type_param.DefineType (this)) return false; } } member_cache = new MemberCache (TypeManager.multicast_delegate_type, this); // FIXME: POSSIBLY make this static, as it is always constant // Type [] const_arg_types = new Type [2]; const_arg_types [0] = TypeManager.object_type; const_arg_types [1] = TypeManager.intptr_type; const MethodAttributes ctor_mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public; ConstructorBuilder = TypeBuilder.DefineConstructor (ctor_mattr, CallingConventions.Standard, const_arg_types); ConstructorBuilder.DefineParameter (1, ParameterAttributes.None, "object"); ConstructorBuilder.DefineParameter (2, ParameterAttributes.None, "method"); // // HACK because System.Reflection.Emit is lame // IParameterData [] fixed_pars = new IParameterData [] { new ParameterData ("object", Parameter.Modifier.NONE), new ParameterData ("method", Parameter.Modifier.NONE) }; AParametersCollection const_parameters = new ParametersImported ( fixed_pars, new Type[] { TypeManager.object_type, TypeManager.intptr_type }); TypeManager.RegisterMethod (ConstructorBuilder, const_parameters); member_cache.AddMember (ConstructorBuilder, this); ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); // // Here the various methods like Invoke, BeginInvoke etc are defined // // First, call the `out of band' special method for // defining recursively any types we need: if (!Parameters.Resolve (this)) return false; // // Invoke method // // Check accessibility foreach (Type partype in Parameters.Types){ if (!IsAccessibleAs (partype)) { Report.SymbolRelatedToPreviousError (partype); Report.Error (59, Location, "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'", TypeManager.CSharpName (partype), GetSignatureForError ()); return false; } } ReturnType = ReturnType.ResolveAsTypeTerminal (this, false); if (ReturnType == null) return false; ret_type = ReturnType.Type; if (!IsAccessibleAs (ret_type)) { Report.SymbolRelatedToPreviousError (ret_type); Report.Error (58, Location, "Inconsistent accessibility: return type `" + TypeManager.CSharpName (ret_type) + "' is less " + "accessible than delegate `" + GetSignatureForError () + "'"); return false; } CheckProtectedModifier (); if (RootContext.StdLib && TypeManager.IsSpecialType (ret_type)) { Method.Error1599 (Location, ret_type, Report); return false; } TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this); // // We don't have to check any others because they are all // guaranteed to be accessible - they are standard types. // CallingConventions cc = Parameters.CallingConvention; InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", mattr, cc, ret_type, Parameters.GetEmitTypes ()); InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); TypeManager.RegisterMethod (InvokeBuilder, Parameters); member_cache.AddMember (InvokeBuilder, this); // // Don't emit async method for compiler generated delegates (e.g. dynamic site containers) // if (TypeManager.iasyncresult_type != null && TypeManager.asynccallback_type != null && !IsCompilerGenerated) { DefineAsyncMethods (cc); } return true; }