public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) { throw new NotImplementedException (); }
public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) { throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ()); }
public void AddInterface (MemberCache baseCache) { if (baseCache.member_hash.Count > 0) AddCacheContents (baseCache); }
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; try { imported = importer.CreateNestedType (t, declaringType); } catch (Exception e) { throw new InternalErrorException (e, "Could not import nested type `{0}' from `{1}'", t.FullName, declaringType.MemberDefinition.DeclaringAssembly.FullName); } 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); } } // // Load base interfaces first to minic behaviour of compiled members // if (declaringType.IsInterface && declaringType.Interfaces != null) { foreach (var iface in declaringType.Interfaces) { cache.AddInterface (iface); } } 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 (MetadataImporter.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); } } }
/// <summary> /// Bootstrap this member cache by doing a deep-copy of our base. /// </summary> static Hashtable SetupCache (MemberCache base_class) { if (base_class == null) return new Hashtable (); Hashtable hash = new Hashtable (base_class.member_hash.Count); IDictionaryEnumerator it = base_class.member_hash.GetEnumerator (); while (it.MoveNext ()) { hash.Add (it.Key, ((ArrayList) it.Value).Clone ()); } return hash; }
/// <summary> /// Add the contents of `cache' to the member_hash. /// </summary> void AddCacheContents (MemberCache cache) { IDictionaryEnumerator it = cache.member_hash.GetEnumerator (); while (it.MoveNext ()) { ArrayList list = (ArrayList) member_hash [it.Key]; if (list == null) member_hash [it.Key] = list = new ArrayList (); ArrayList entries = (ArrayList) it.Value; for (int i = entries.Count-1; i >= 0; i--) { CacheEntry entry = (CacheEntry) entries [i]; if (entry.Container != cache.Container) break; list.Add (entry); } } }
// // Populates type parameter members using type parameter constraints // The trick here is to be called late enough but not too late to // populate member cache with all members from other types // protected override void InitializeMemberCache (bool onlyTypes) { cache = new MemberCache (); if (ifaces != null) { foreach (var iface_type in Interfaces) { cache.AddInterface (iface_type); } } }
/// <summary> /// Populates our TypeBuilder with fields and methods /// </summary> public override bool DefineMembers (TypeContainer parent) { MemberInfo [] defined_names = null; if (interface_order != null){ foreach (Interface iface in interface_order) if ((iface.ModFlags & Modifiers.NEW) == 0) iface.DefineMembers (this); else Error_KeywordNotAllowed (iface.Location); } if (RootContext.WarningLevel > 1){ Type ptype; // // This code throws an exception in the comparer // I guess the string is not an object? // ptype = TypeBuilder.BaseType; if (ptype != null){ defined_names = (MemberInfo []) FindMembers ( ptype, MemberTypes.All & ~MemberTypes.Constructor, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, null, null); Array.Sort (defined_names, mif_compare); } } if (constants != null) DefineMembers (constants, defined_names); if (fields != null) DefineMembers (fields, defined_names); if (this is Class){ if (instance_constructors == null){ if (default_constructor == null) DefineDefaultConstructor (false); } if (initialized_static_fields != null && default_static_constructor == null) DefineDefaultConstructor (true); } if (this is Struct){ // // Structs can not have initialized instance // fields // if (initialized_static_fields != null && default_static_constructor == null) DefineDefaultConstructor (true); if (initialized_fields != null) ReportStructInitializedInstanceError (); } Pending = PendingImplementation.GetPendingImplementations (this); // // Constructors are not in the defined_names array // if (instance_constructors != null) DefineMembers (instance_constructors, null); if (default_static_constructor != null) default_static_constructor.Define (this); if (methods != null) DefineMembers (methods, defined_names); if (properties != null) DefineMembers (properties, defined_names); if (events != null) DefineMembers (events, defined_names); if (indexers != null) { DefineIndexers (); } else IndexerName = "Item"; if (operators != null){ DefineMembers (operators, null); CheckPairedOperators (); } if (enums != null) DefineMembers (enums, defined_names); if (delegates != null) DefineMembers (delegates, defined_names); #if CACHE if (TypeBuilder.BaseType != null) parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType); member_cache = new MemberCache (this); #endif return true; }
protected override void InitializeMemberCache (bool onlyTypes) { if (cache == null) cache = new MemberCache (onlyTypes ? open_type.MemberCacheTypes : open_type.MemberCache); TypeParameterSpec[] tparams_full; TypeSpec[] targs_full = targs; if (IsNested) { // // Special case is needed when we are inflating an open type (nested type definition) // on inflated parent. Consider following case // // Foo<T>.Bar<U> => Foo<string>.Bar<U> // // Any later inflation of Foo<string>.Bar<U> has to also inflate T if used inside Bar<U> // List<TypeSpec> merged_targs = null; List<TypeParameterSpec> merged_tparams = null; var type = DeclaringType; do { if (type.TypeArguments.Length > 0) { if (merged_targs == null) { merged_targs = new List<TypeSpec> (); merged_tparams = new List<TypeParameterSpec> (); if (targs.Length > 0) { merged_targs.AddRange (targs); merged_tparams.AddRange (open_type.MemberDefinition.TypeParameters); } } merged_tparams.AddRange (type.MemberDefinition.TypeParameters); merged_targs.AddRange (type.TypeArguments); } type = type.DeclaringType; } while (type != null); if (merged_targs != null) { // Type arguments are not in the right order but it should not matter in this case targs_full = merged_targs.ToArray (); tparams_full = merged_tparams.ToArray (); } else if (targs.Length == 0) { tparams_full = TypeParameterSpec.EmptyTypes; } else { tparams_full = open_type.MemberDefinition.TypeParameters; } } else if (targs.Length == 0) { tparams_full = TypeParameterSpec.EmptyTypes; } else { tparams_full = open_type.MemberDefinition.TypeParameters; } var inflator = new TypeParameterInflator (this, tparams_full, targs_full); // // Two stage inflate due to possible nested types recursive // references // // class A<T> { // B b; // class B { // T Value; // } // } // // When resolving type of `b' members of `B' cannot be // inflated because are not yet available in membercache // if ((state & StateFlags.PendingMemberCacheMembers) == 0) { open_type.MemberCacheTypes.InflateTypes (cache, inflator); // // Inflate any implemented interfaces // if (open_type.Interfaces != null) { ifaces = new List<TypeSpec> (open_type.Interfaces.Count); foreach (var iface in open_type.Interfaces) { var iface_inflated = inflator.Inflate (iface); AddInterface (iface_inflated); } } // // Handles the tricky case of recursive nested base generic type // // class A<T> : Base<A<T>.Nested> { // class Nested {} // } // // When inflating A<T>. base type is not yet known, secondary // inflation is required (not common case) once base scope // is known // if (open_type.BaseType == null) { if (IsClass) state |= StateFlags.PendingBaseTypeInflate; } else { BaseType = inflator.Inflate (open_type.BaseType); } } else if ((state & StateFlags.PendingBaseTypeInflate) != 0) { BaseType = inflator.Inflate (open_type.BaseType); state &= ~StateFlags.PendingBaseTypeInflate; } if (onlyTypes) { state |= StateFlags.PendingMemberCacheMembers; return; } var tc = open_type.MemberDefinition as TypeContainer; if (tc != null && !tc.HasMembersDefined) throw new InternalErrorException ("Inflating MemberCache with undefined members"); if ((state & StateFlags.PendingBaseTypeInflate) != 0) { BaseType = inflator.Inflate (open_type.BaseType); state &= ~StateFlags.PendingBaseTypeInflate; } state &= ~StateFlags.PendingMemberCacheMembers; open_type.MemberCache.InflateMembers (cache, open_type, inflator); }
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; }
public override bool Define () { member_cache = new MemberCache (TypeManager.enum_type, this); DefineContainerMembers (constants); return true; }
public override void CloseType () { if ((caching_flags & Flags.CloseTypeCreated) != 0) return; try { caching_flags |= Flags.CloseTypeCreated; TypeBuilder.CreateType (); } catch (TypeLoadException){ // // This is fine, the code still created the type // // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name); // Console.WriteLine (e.Message); } catch (Exception e) { throw new InternalErrorException (this, e); } if (Types != null){ foreach (TypeContainer tc in Types) if (tc.Kind == Kind.Struct) tc.CloseType (); foreach (TypeContainer tc in Types) if (tc.Kind != Kind.Struct) tc.CloseType (); } if (Delegates != null) foreach (Delegate d in Delegates) d.CloseType (); if (compiler_generated != null) foreach (CompilerGeneratedClass c in compiler_generated) c.CloseType (); PartialContainer = null; types = null; // properties = null; delegates = null; fields = null; initialized_fields = null; initialized_static_fields = null; constants = null; ordered_explicit_member_list = null; ordered_member_list = null; methods = null; events = null; indexers = null; operators = null; compiler_generated = null; default_constructor = null; default_static_constructor = null; type_bases = null; OptAttributes = null; ifaces = null; base_cache = null; member_cache = null; }
protected virtual bool DoDefineMembers () { if (iface_exprs != null) { foreach (TypeExpr iface in iface_exprs) { ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (iface.Type); if ((oa != null) && !IsObsolete) AttributeTester.Report_ObsoleteMessage ( oa, iface.GetSignatureForError (), Location, Report); GenericTypeExpr ct = iface as GenericTypeExpr; if (ct != null) { // TODO: passing `this' is wrong, should be base type iface instead TypeManager.CheckTypeVariance (ct.Type, Variance.Covariant, this); if (!ct.CheckConstraints (this)) return false; } } } if (base_type != null) { ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type); if (obsolete_attr != null && !IsObsolete) AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location, Report); GenericTypeExpr ct = base_type as GenericTypeExpr; if ((ct != null) && !ct.CheckConstraints (this)) return false; TypeContainer baseContainer = TypeManager.LookupTypeContainer(base_type.Type); if (baseContainer != null) baseContainer.Define(); member_cache = new MemberCache (base_type.Type, this); } else if (Kind == Kind.Interface) { member_cache = new MemberCache (null, this); Type [] ifaces = TypeManager.GetInterfaces (TypeBuilder); for (int i = 0; i < ifaces.Length; ++i) member_cache.AddInterface (TypeManager.LookupMemberCache (ifaces [i])); } else { member_cache = new MemberCache (null, this); } if (types != null) foreach (TypeContainer tc in types) member_cache.AddNestedType (tc); if (delegates != null) foreach (Delegate d in delegates) member_cache.AddNestedType (d); if (partial_parts != null) { foreach (TypeContainer part in partial_parts) part.member_cache = member_cache; } if (!IsTopLevel) { MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Basename, false); if (conflict_symbol == null) { if ((ModFlags & Modifiers.NEW) != 0) Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ()); } else { if ((ModFlags & Modifiers.NEW) == 0) { Report.SymbolRelatedToPreviousError (conflict_symbol); Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol)); } } } DefineContainerMembers (constants); DefineContainerMembers (fields); if (Kind == Kind.Struct || Kind == Kind.Class) { pending = PendingImplementation.GetPendingImplementations (this); if (requires_delayed_unmanagedtype_check) { requires_delayed_unmanagedtype_check = false; foreach (FieldBase f in fields) { if (f.MemberType != null && f.MemberType.IsPointer) TypeManager.VerifyUnManaged (f.MemberType, f.Location); } } } // // Constructors are not in the defined_names array // DefineContainerMembers (instance_constructors); DefineContainerMembers (events); DefineContainerMembers (ordered_explicit_member_list); DefineContainerMembers (ordered_member_list); DefineContainerMembers (operators); DefineContainerMembers (delegates); ComputeIndexerName(); CheckEqualsAndGetHashCode(); if (CurrentType != null) { GenericType = CurrentType; } // // FIXME: This hack is needed because member cache does not work // with generic types, we rely on runtime to inflate dynamic types. // TODO: This hack requires member cache refactoring to be removed // if (TypeManager.IsGenericType (TypeBuilder)) member_cache = new MemberCache (this); return true; }