📄 decl.cs
字号:
caching_flags |= Flags.ClsCompliantAttributeTrue; return true; } return false; } if (Parent.GetClsCompliantAttributeValue ()) { caching_flags |= Flags.ClsCompliantAttributeTrue; return true; } return false; } public override string[] ValidAttributeTargets { get { return attribute_targets; } } protected override bool VerifyClsCompliance (DeclSpace ds) { if (!base.VerifyClsCompliance (ds)) { return false; } IDictionary cache = TypeManager.AllClsTopLevelTypes; string lcase = Name.ToLower (System.Globalization.CultureInfo.InvariantCulture); if (!cache.Contains (lcase)) { cache.Add (lcase, this); return true; } object val = cache [lcase]; if (val == null) { Type t = AttributeTester.GetImportedIgnoreCaseClsType (lcase); if (t == null) return true; Report.SymbolRelatedToPreviousError (t); } else { if (val is PartialContainer) return true; Report.SymbolRelatedToPreviousError ((DeclSpace)val); } Report.Error (3005, Location, "Identifier `{0}' differing only in case is not CLS-compliant", GetSignatureForError ()); return true; } } /// <summary> /// This is a readonly list of MemberInfo's. /// </summary> public class MemberList : IList { public readonly IList List; int count; /// <summary> /// Create a new MemberList from the given IList. /// </summary> public MemberList (IList list) { if (list != null) this.List = list; else this.List = new ArrayList (); count = List.Count; } /// <summary> /// Concatenate the ILists `first' and `second' to a new MemberList. /// </summary> public MemberList (IList first, IList second) { ArrayList list = new ArrayList (); list.AddRange (first); list.AddRange (second); count = list.Count; List = list; } public static readonly MemberList Empty = new MemberList (new ArrayList ()); /// <summary> /// Cast the MemberList into a MemberInfo[] array. /// </summary> /// <remarks> /// This is an expensive operation, only use it if it's really necessary. /// </remarks> public static explicit operator MemberInfo [] (MemberList list) { Timer.StartTimer (TimerType.MiscTimer); MemberInfo [] result = new MemberInfo [list.Count]; list.CopyTo (result, 0); Timer.StopTimer (TimerType.MiscTimer); return result; } // ICollection public int Count { get { return count; } } public bool IsSynchronized { get { return List.IsSynchronized; } } public object SyncRoot { get { return List.SyncRoot; } } public void CopyTo (Array array, int index) { List.CopyTo (array, index); } // IEnumerable public IEnumerator GetEnumerator () { return List.GetEnumerator (); } // IList public bool IsFixedSize { get { return true; } } public bool IsReadOnly { get { return true; } } object IList.this [int index] { get { return List [index]; } set { throw new NotSupportedException (); } } // FIXME: try to find out whether we can avoid the cast in this indexer. public MemberInfo this [int index] { get { return (MemberInfo) List [index]; } } public int Add (object value) { throw new NotSupportedException (); } public void Clear () { throw new NotSupportedException (); } public bool Contains (object value) { return List.Contains (value); } public int IndexOf (object value) { return List.IndexOf (value); } public void Insert (int index, object value) { throw new NotSupportedException (); } public void Remove (object value) { throw new NotSupportedException (); } public void RemoveAt (int index) { throw new NotSupportedException (); } } /// <summary> /// This interface is used to get all members of a class when creating the /// member cache. It must be implemented by all DeclSpace derivatives which /// want to support the member cache and by TypeHandle to get caching of /// non-dynamic types. /// </summary> public interface IMemberContainer { /// <summary> /// The name of the IMemberContainer. This is only used for /// debugging purposes. /// </summary> string Name { get; } /// <summary> /// The type of this IMemberContainer. /// </summary> Type Type { get; } /// <summary> /// Returns the IMemberContainer of the base class or null if this /// is an interface or TypeManger.object_type. /// This is used when creating the member cache for a class to get all /// members from the base class. /// </summary> MemberCache BaseCache { get; } /// <summary> /// Whether this is an interface. /// </summary> bool IsInterface { get; } /// <summary> /// Returns all members of this class with the corresponding MemberTypes /// and BindingFlags. /// </summary> /// <remarks> /// When implementing this method, make sure not to return any inherited /// members and check the MemberTypes and BindingFlags properly. /// Unfortunately, System.Reflection is lame and doesn't provide a way to /// get the BindingFlags (static/non-static,public/non-public) in the /// MemberInfo class, but the cache needs this information. That's why /// this method is called multiple times with different BindingFlags. /// </remarks> MemberList GetMembers (MemberTypes mt, BindingFlags bf); /// <summary> /// Return the container's member cache. /// </summary> MemberCache MemberCache { get; } } /// <summary> /// The MemberCache is used by dynamic and non-dynamic types to speed up /// member lookups. It has a member name based hash table; it maps each member /// name to a list of CacheEntry objects. Each CacheEntry contains a MemberInfo /// and the BindingFlags that were initially used to get it. The cache contains /// all members of the current class and all inherited members. If this cache is /// for an interface types, it also contains all inherited members. /// /// There are two ways to get a MemberCache: /// * if this is a dynamic type, lookup the corresponding DeclSpace and then /// use the DeclSpace.MemberCache property. /// * if this not a dynamic type, call TypeHandle.GetTypeHandle() to get a /// TypeHandle instance for the type and then use TypeHandle.MemberCache. /// </summary> public class MemberCache { public readonly IMemberContainer Container; protected Hashtable member_hash; protected Hashtable method_hash; /// <summary> /// Create a new MemberCache for the given IMemberContainer `container'. /// </summary> public MemberCache (IMemberContainer container) { this.Container = container; Timer.IncrementCounter (CounterType.MemberCache); Timer.StartTimer (TimerType.CacheInit); // If we have a base class (we have a base class unless we're // TypeManager.object_type), we deep-copy its MemberCache here. if (Container.BaseCache != null) member_hash = SetupCache (Container.BaseCache); else member_hash = new Hashtable (); // If this is neither a dynamic type nor an interface, create a special // method cache with all declared and inherited methods. Type type = container.Type; if (!(type is TypeBuilder) && !type.IsInterface && (Container.BaseCache == null || Container.BaseCache.method_hash != null)) { method_hash = new Hashtable (); AddMethods (type); } // Add all members from the current class. AddMembers (Container); Timer.StopTimer (TimerType.CacheInit); } public MemberCache (Type[] ifaces) { // // The members of this cache all belong to other caches. // So, 'Container' will not be used. // this.Container = null; member_hash = new Hashtable (); if (ifaces == null) return; foreach (Type itype in ifaces) AddCacheContents (TypeManager.LookupMemberCache (itype)); } /// <summary> /// Bootstrap this member cache by doing a deep-copy of our base. /// </summary> Hashtable SetupCache (MemberCache base_class) { Hashtable hash = new Hashtable (); if (base_class == null) return hash; IDictionaryEnumerator it = base_class.member_hash.GetEnumerator (); while (it.MoveNext ()) { hash [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); } } } /// <summary> /// Add all members from class `container' to the cache. /// </summary> void AddMembers (IMemberContainer container) { // We need to call AddMembers() with a single member type at a time // to get the member type part of CacheEntry.EntryType right. if (!container.IsInterface) { AddMembers (MemberTypes.Constructor, container); AddMembers (MemberTypes.Field, container); } AddMembers (MemberTypes.Method, container); AddMembers (MemberTypes.Property, container); AddMembers (MemberTypes.Event, container); // Nested types are returned by both Static and Instance searches. AddMembers (MemberTypes.NestedType, BindingFlags.Static | BindingFlags.Public, container); AddMembers (MemberTypes.NestedType, BindingFlags.Static | BindingFlags.NonPublic, container); } void AddMembers (MemberTypes mt, IMemberContainer container) { AddMembers (mt, BindingFlags.Static | BindingFlags.Public, container); AddMembers (mt, BindingFlags.Static | BindingFlags.NonPublic, container); AddMembers (mt, BindingFlags.Instance | BindingFlags.Public, container); AddMembers (mt, BindingFlags.Instance | BindingFlags.NonPublic, container); } /// <summary> /// Add all members from class `container' with the requested MemberTypes and /// BindingFlags to the cache. This method is called multiple times with different /// MemberTypes and BindingFlags. /// </summary> void AddMembers (MemberTypes mt, BindingFlags bf, IMemberContainer container) { MemberList members = container.GetMembers (mt, bf); foreach (MemberInfo member in members) { string name = member.Name; // We use a name-based hash table of ArrayList's. ArrayList list = (ArrayList) member_hash [name]; if (list == null) { list = new ArrayList (); member_hash.Add (name, list); } // When this method is called for the current class, the list will // already contain all inherited members from our base classes. // We cannot add new members in front of the list since this'd be an // expensive operation, that's why the list is sorted in reverse order // (ie. members from the current class are coming last). list.Add (new CacheEntry (container, member, mt, bf)); } } /// <summary> /// Add all declared and inherited methods from class `type' to the method cache. /// </summary> void AddMethods (Type type) { AddMethods (BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy, type); AddMethods (BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy, type); AddMethods (BindingFlags.Instance | BindingFlags.Public, type); AddMethods (BindingFlags.Instance | BindingFlags.NonPublic, type); } static ArrayList overrides = new ArrayList (); void AddMethods (BindingFlags bf, Type type) { MethodBase [] members = type.GetMethods (bf); Array.Reverse (members); foreach (MethodBase member in members) { string name = member.Name; // We use a name-based hash table of ArrayList's. ArrayList list = (ArrayList) method_hash [name]; if (list == null) { list = new ArrayList (); method_hash.Add (name, list); } MethodInfo curr = (MethodInfo) member; while (curr.IsVirtual && (curr.Attributes & MethodAttributes.NewSlot) == 0) { MethodInfo base_method = curr.GetBaseDefinition (); if (base_method == curr) // Not every virtual function needs to have a NewSlot flag. break; overrides.Add (curr); list.Add (new CacheEntry (null, base_method, MemberTypes.Method, bf)); curr = base_method; } if (overrides.Count > 0) { for (int i = 0; i < overrides.Count; ++i) TypeManager.RegisterOverride ((MethodBase) overrides [i], curr); overrides.Clear (); } // Unfortunately, the elements returned by Type.GetMethods() aren't // sorted so we need to do this check for every member. BindingFlags new_bf = bf; if (member.DeclaringType == type) new_bf |= BindingFlags.DeclaredOnly; list.Add (new CacheEntry (Container, member, MemberTypes.Method, new_bf)); } } /// <summary> /// Compute and return a appropriate `EntryType' magic number for the given /// MemberTypes and BindingFlags. /// </summary> protected static EntryType GetEntryType (MemberTypes mt, BindingFlags bf) { EntryType type = EntryType.None; if ((mt & MemberTypes.Constructor) != 0) type |= EntryType.Constructor; if ((mt & MemberTypes.Event) != 0) type |= EntryType.Event; if ((mt & MemberTypes.Field) != 0) type |= EntryType.Field; if ((mt & MemberTypes.Method) != 0) type |= EntryType.Method; if ((mt & MemberTypes.Property) != 0) type |= EntryType.Property; // Nested types are returned by static and instance searches. if ((mt & MemberTypes.NestedType) != 0) type |= EntryType.NestedType | EntryType.Static | EntryType.Instance; if ((bf & BindingFlags.Instance) != 0) type |= EntryType.Instance; if ((bf & BindingFlags.Static) != 0) type |= EntryType.Static; if ((bf & BindingFlags.Public) != 0) type |= EntryType.Public; if ((bf & BindingFlags.NonPublic) != 0) type |= EntryType.NonPublic; if ((bf & BindingFlags.DeclaredOnly) != 0) type |= EntryType.Declared; return type; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -