+#endregion
+
+}
+
+public class MemberCache {
+ public readonly IMemberContainer Container;
+ protected Hashtable MemberHash;
+
+ public MemberCache (IMemberContainer container)
+ {
+ this.Container = container;
+ this.MemberHash = new Hashtable ();
+
+ Timer.IncrementCounter (CounterType.MemberCache);
+ Timer.StartTimer (TimerType.CacheInit);
+
+ AddMembers (true);
+ AddMembers (false);
+
+ Timer.StopTimer (TimerType.CacheInit);
+ }
+
+ void AddMembers (bool declared)
+ {
+ AddMembers (MemberTypes.Constructor, declared);
+ AddMembers (MemberTypes.Event, declared);
+ AddMembers (MemberTypes.Field, declared);
+ AddMembers (MemberTypes.Method, declared);
+ AddMembers (MemberTypes.Property, declared);
+ AddMembers (MemberTypes.NestedType, declared);
+ }
+
+ void AddMembers (MemberTypes mt, bool declared)
+ {
+ AddMembers (mt, BindingFlags.Static | BindingFlags.Public, declared);
+ AddMembers (mt, BindingFlags.Static | BindingFlags.NonPublic, declared);
+ AddMembers (mt, BindingFlags.Instance | BindingFlags.Public, declared);
+ AddMembers (mt, BindingFlags.Instance | BindingFlags.NonPublic, declared);
+ }
+
+ void AddMembers (MemberTypes mt, BindingFlags bf, bool declared)
+ {
+ MemberList members = Container.GetMembers (mt, bf, declared);
+ BindingFlags new_bf = declared ? bf | BindingFlags.DeclaredOnly : bf;
+
+ foreach (MemberInfo member in members) {
+ string name = member.Name;
+
+ ArrayList list = (ArrayList) MemberHash [name];
+ if (list == null) {
+ list = new ArrayList ();
+ MemberHash.Add (name, list);
+ }
+
+ list.Add (new CacheEntry (member, mt, new_bf));
+ }
+ }
+
+ 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;
+ if ((mt & MemberTypes.NestedType) != 0)
+ type |= EntryType.NestedType;
+
+ 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;
+ }
+
+ public static bool IsSingleMemberType (MemberTypes mt)
+ {
+ switch (mt) {
+ case MemberTypes.Constructor:
+ case MemberTypes.Event:
+ case MemberTypes.Field:
+ case MemberTypes.Method:
+ case MemberTypes.Property:
+ case MemberTypes.NestedType:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ [Flags]
+ protected enum EntryType {
+ None = 0x000,
+
+ Instance = 0x001,
+ Static = 0x002,
+ MaskStatic = Instance|Static,
+
+ Public = 0x004,
+ NonPublic = 0x008,
+ MaskProtection = Public|NonPublic,
+
+ Declared = 0x010,
+
+ Constructor = 0x020,
+ Event = 0x040,
+ Field = 0x080,
+ Method = 0x100,
+ Property = 0x200,
+ NestedType = 0x400,
+
+ MaskType = Constructor|Event|Field|Method|Property|NestedType
+ }
+
+ protected struct CacheEntry {
+ public EntryType EntryType;
+ public MemberInfo Member;
+
+ public CacheEntry (MemberInfo member, MemberTypes mt, BindingFlags bf)
+ {
+ this.Member = member;
+ this.EntryType = GetEntryType (mt, bf);
+ }
+ }
+
+ protected void SearchMembers (ArrayList list, MemberTypes mt, BindingFlags bf, IList applicable,
+ MemberFilter filter, object criteria)
+ {
+ bool declared_only = (bf & BindingFlags.DeclaredOnly) != 0;
+ EntryType type = GetEntryType (mt, bf);
+
+ foreach (CacheEntry entry in applicable) {
+ if (declared_only && ((entry.EntryType & EntryType.Declared) == 0))
+ continue;
+
+ if ((entry.EntryType & type & EntryType.MaskType) == 0)
+ continue;
+
+ if ((entry.EntryType & type & EntryType.MaskStatic) == 0)
+ continue;
+
+ if (filter (entry.Member, criteria))
+ list.Add (entry.Member);
+ }
+ }
+
+ public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
+ MemberFilter filter, object criteria)
+ {
+ IList applicable = (IList) MemberHash [name];
+ if (applicable == null)
+ return MemberList.Empty;
+
+ ArrayList list = new ArrayList ();
+
+ if ((bf & BindingFlags.Static) != 0) {
+ SearchMembers (list, mt, bf & ~BindingFlags.Instance, applicable,
+ filter, criteria);
+
+ if (list.Count == 1){
+ MemberInfo one = (MemberInfo) list [0];
+
+ //
+ // If any of these are present, we are done!
+ //
+ if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
+ return new MemberList (list);
+ }
+ }
+
+ if ((bf & BindingFlags.Instance) != 0)
+ SearchMembers (list, mt, bf & ~BindingFlags.Static, applicable,
+ filter, criteria);
+
+ return new MemberList (list);
+ }
+}
+
+public class TypeHandle : IMemberContainer {
+ public readonly Type Type;
+ public readonly Type BaseType;
+ public readonly MemberCache MemberCache;
+
+ public TypeHandle (Type t)
+ {
+ this.Type = t;
+ this.BaseType = t.BaseType;
+ this.MemberCache = new MemberCache (this);
+ }
+
+ public MemberList GetMembers (MemberTypes mt, BindingFlags bf, bool declared)
+ {
+ if (declared)
+ return new MemberList (Type.FindMembers (
+ mt, bf | BindingFlags.DeclaredOnly, null, null));
+
+ if (BaseType == null)
+ return MemberList.Empty;
+
+ return new MemberList (BaseType.FindMembers (mt, bf, null, null));
+ }
+
+ public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
+ MemberFilter filter, object criteria)
+ {
+ MemberList list;
+
+ Timer.StartTimer (TimerType.CachedLookup);
+ list = MemberCache.FindMembers (mt, bf, name, filter, criteria);
+ Timer.StopTimer (TimerType.CachedLookup);
+
+ return list;
+ }