Code:
/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / RtType.cs / 9 / RtType.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== using System; using System.Reflection; using System.Runtime.ConstrainedExecution; using System.Globalization; using System.Threading; using System.Diagnostics; using System.Security.Permissions; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; using System.Runtime.CompilerServices; using System.Security; using System.Text; using System.Reflection.Emit; using System.Runtime.Remoting; using System.Runtime.Remoting.Proxies; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Activation; using MdSigCallingConvention = System.Signature.MdSigCallingConvention; using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache; using System.Runtime.InteropServices; using DebuggerStepThroughAttribute = System.Diagnostics.DebuggerStepThroughAttribute; using MdToken = System.Reflection.MetadataToken; namespace System { // this is a work around to get the concept of a calli. It's not as fast but it would be interesting to // see how it compares to the current implementation. // This delegate will disappear at some point in favor of calli internal delegate void CtorDelegate(Object instance); [Serializable()] internal class RuntimeType : Type, ISerializable, ICloneable { #region Definitions [Serializable()] internal class RuntimeTypeCache { #region Definitions internal enum WhatsCached { Nothing = 0x0, EnclosingType = 0x1, } internal enum CacheType { Method, Constructor, Field, Property, Event, Interface, NestedType } // This method serves two purposes, both enabling optimizations in ngen image // First, it tells ngen which instantiations of MemberInfoCache to save in the ngen image // Second, it ensures MemberInfoCache<*Info>.Insert methods are pre-prepared in the // ngen image, and any runtime preparation that needs to happen, happens in the Prestub // worker of Prejitinit_Hack. At runtime we do not really want to execute the Insert methods // here; the calls are present just to fool the CER preparation code into preparing those methods during ngen internal static void Prejitinit_HACK() { // make sure this conditional is around everything _including_ the call to // PrepareConstrainedRegions, the JIT/NGen just needs to see the callsite // somewhere, but the callsite has a link demand which can trip up partially // trusted code. if (!s_dontrunhack) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { MemberInfoCachemicrmi = new MemberInfoCache (null); CerArrayList list =null; micrmi.Insert(ref list, "dummy", MemberListType.All); MemberInfoCache micrci = new MemberInfoCache (null); CerArrayList listc =null; micrci.Insert(ref listc, "dummy", MemberListType.All); MemberInfoCache micrfi = new MemberInfoCache (null); CerArrayList listf =null; micrfi.Insert(ref listf, "dummy", MemberListType.All); MemberInfoCache micri = new MemberInfoCache (null); CerArrayList listi =null; micri.Insert(ref listi, "dummy", MemberListType.All); MemberInfoCache micrpi = new MemberInfoCache (null); CerArrayList listp =null; micrpi.Insert(ref listp, "dummy", MemberListType.All); MemberInfoCache micrei = new MemberInfoCache (null); CerArrayList liste =null; micrei.Insert(ref liste, "dummy", MemberListType.All); } } } private struct Filter { private Utf8String m_name; private MemberListType m_listType; public unsafe Filter(byte* pUtf8Name, int cUtf8Name, MemberListType listType) { this.m_name = new Utf8String((void*) pUtf8Name, cUtf8Name); this.m_listType = listType; } public bool Match(Utf8String name) { if (m_listType == MemberListType.CaseSensitive) return m_name.Equals(name); else if (m_listType == MemberListType.CaseInsensitive) return m_name.EqualsCaseInsensitive(name); else return true; } } [Serializable()] private class MemberInfoCache where T : MemberInfo { #region Static Members static MemberInfoCache() { // We need to prepare some code in this class for reliable // execution on a per-instantiation basis. A static class // constructor is ideal for this since we only need to do // this once per-instantiation. We can't go through the // normal approach using RuntimeHelpers.PrepareMethod since // that would involve using reflection and we'd wind back up // here recursively. So we call through an fcall helper // instead. The fcall is on RuntimeType to avoid having an // fcall entry for a nested class (a generic one at that). // I've no idea if that would work, but I'm pretty sure it // wouldn't. Also we pass in our own base type since using // the mscorlib binder doesn't work for nested types (I've // tried that one). PrepareMemberInfoCache(typeof(MemberInfoCache ).TypeHandle); } #endregion #region Private Data Members // MemberInfo caches private CerHashtable > m_csMemberInfos; private CerHashtable > m_cisMemberInfos; private CerArrayList m_root; private bool m_cacheComplete; // This is the strong reference back to the cache private RuntimeTypeCache m_runtimeTypeCache; #endregion #region Constructor internal MemberInfoCache(RuntimeTypeCache runtimeTypeCache) { #if MDA_SUPPORTED Mda.MemberInfoCacheCreation(); #endif m_runtimeTypeCache = runtimeTypeCache; m_cacheComplete = false; } internal MethodBase AddMethod(RuntimeTypeHandle declaringType, RuntimeMethodHandle method, CacheType cacheType) { Object list = null; MethodAttributes methodAttributes = method.GetAttributes(); bool isPublic = (methodAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; bool isStatic = (methodAttributes & MethodAttributes.Static) != 0; bool isInherited = declaringType.Value != ReflectedTypeHandle.Value; BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic); switch (cacheType) { case CacheType.Method: List mlist = new List (1); mlist.Add(new RuntimeMethodInfo(method, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags)); list = mlist; break; case CacheType.Constructor: List clist = new List (1); clist.Add(new RuntimeConstructorInfo(method, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags)); list = clist; break; } CerArrayList cerList = new CerArrayList ((List )list); Insert(ref cerList, null, MemberListType.HandleToInfo); return (MethodBase)(object)cerList[0]; } internal FieldInfo AddField(RuntimeFieldHandle field) { // create the runtime field info List list = new List (1); FieldAttributes fieldAttributes = field.GetAttributes(); bool isPublic = (fieldAttributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public; bool isStatic = (fieldAttributes & FieldAttributes.Static) != 0; bool isInherited = field.GetApproxDeclaringType().Value != ReflectedTypeHandle.Value; BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic); list.Add(new RtFieldInfo(field, ReflectedType, m_runtimeTypeCache, bindingFlags)); CerArrayList cerList = new CerArrayList ((List )(object)list); Insert(ref cerList, null, MemberListType.HandleToInfo); return (FieldInfo)(object)cerList[0]; } private unsafe CerArrayList Populate(string name, MemberListType listType, CacheType cacheType) { if (name == null || name.Length == 0 || (cacheType == CacheType.Constructor && name.FirstChar != '.' && name.FirstChar != '*')) { Filter filter = new Filter(null, 0, listType); List list = null; switch (cacheType) { case CacheType.Method: list = PopulateMethods(filter) as List ; break; case CacheType.Field : list = PopulateFields(filter) as List ; break; case CacheType.Constructor : list = PopulateConstructors(filter) as List ; break; case CacheType.Property : list = PopulateProperties(filter) as List ; break; case CacheType.Event : list = PopulateEvents(filter) as List ; break; case CacheType.NestedType : list = PopulateNestedClasses(filter) as List ; break; case CacheType.Interface : list = PopulateInterfaces(filter) as List ; break; } CerArrayList cerList = new CerArrayList (list); Insert(ref cerList, name, listType); return cerList; } else { fixed (char* pName = name) { int cUtf8Name = Encoding.UTF8.GetByteCount(pName, name.Length); byte* pUtf8Name = stackalloc byte[cUtf8Name]; Encoding.UTF8.GetBytes(pName, name.Length, pUtf8Name, cUtf8Name); Filter filter = new Filter(pUtf8Name, cUtf8Name, listType); List list = null; switch (cacheType) { case CacheType.Method: list = PopulateMethods(filter) as List ; break; case CacheType.Field : list = PopulateFields(filter) as List ; break; case CacheType.Constructor : list = PopulateConstructors(filter) as List ; break; case CacheType.Property : list = PopulateProperties(filter) as List ; break; case CacheType.Event : list = PopulateEvents(filter) as List ; break; case CacheType.NestedType : list = PopulateNestedClasses(filter) as List ; break; case CacheType.Interface : list = PopulateInterfaces(filter) as List ; break; } CerArrayList cerList = new CerArrayList (list); Insert(ref cerList, name, listType); return cerList; } } } // May replace the list with a new one if certain cache // lookups succeed. Also, may modify the contents of the list // after merging these new data structures with cached ones. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal void Insert(ref CerArrayList list, string name, MemberListType listType) { bool lockTaken = false; bool preallocationComplete = false; RuntimeHelpers.PrepareConstrainedRegions(); try { Monitor.ReliableEnter(this, ref lockTaken); if (listType == MemberListType.CaseSensitive) { if (m_csMemberInfos == null) m_csMemberInfos = new CerHashtable >(); else m_csMemberInfos.Preallocate(1); } else if (listType == MemberListType.CaseInsensitive) { if (m_cisMemberInfos == null) m_cisMemberInfos = new CerHashtable >(); else m_cisMemberInfos.Preallocate(1); } if (m_root == null) m_root = new CerArrayList (list.Count); else m_root.Preallocate(list.Count); preallocationComplete = true; } finally { try { if (preallocationComplete) { if (listType == MemberListType.CaseSensitive) { // Ensure we always return a list that has // been merged with the global list. CerArrayList cachedList = m_csMemberInfos[name]; if (cachedList == null) { MergeWithGlobalList(list); m_csMemberInfos[name] = list; } else list = cachedList; } else if (listType == MemberListType.CaseInsensitive) { // Ensure we always return a list that has // been merged with the global list. CerArrayList cachedList = m_cisMemberInfos[name]; if (cachedList == null) { MergeWithGlobalList(list); m_cisMemberInfos[name] = list; } else list = cachedList; } else { MergeWithGlobalList(list); } if (listType == MemberListType.All) { m_cacheComplete = true; } } } finally { if (lockTaken) { Monitor.Exit(this); } } } } // Modifies the existing list. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private void MergeWithGlobalList(CerArrayList list) { int cachedCount = m_root.Count; for (int i = 0; i < list.Count; i++) { T newMemberInfo = list[i]; T cachedMemberInfo = null; for (int j = 0; j < cachedCount; j++) { cachedMemberInfo = m_root[j]; if (newMemberInfo.CacheEquals(cachedMemberInfo)) { list.Replace(i, cachedMemberInfo); break; } } if (list[i] != cachedMemberInfo) m_root.Add(newMemberInfo); } } #endregion #region Population Logic private unsafe List PopulateMethods(Filter filter) { List list = new List (); RuntimeTypeHandle declaringTypeHandle = ReflectedTypeHandle; bool isInterface = (declaringTypeHandle.GetAttributes() & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface; if (isInterface) { #region IsInterface bool mayNeedInstantiatingStub = declaringTypeHandle.HasInstantiation() && !declaringTypeHandle.IsGenericTypeDefinition(); foreach (RuntimeMethodHandle methodHandle in declaringTypeHandle.IntroducedMethods) { if (!filter.Match(methodHandle.GetUtf8Name())) continue; #region Loop through all methods on the interface ASSERT.CONSISTENCY_CHECK(!methodHandle.IsNullHandle()); ASSERT.CONSISTENCY_CHECK(LOGIC.IMPLIES( (methodHandle.GetAttributes() & MethodAttributes.RTSpecialName) != 0, methodHandle.GetName().Equals(".ctor") || methodHandle.GetName().Equals(".cctor") || methodHandle.GetName().Equals("IL_STUB"))); ASSERT.CONSISTENCY_CHECK((methodHandle.GetAttributes() & MethodAttributes.Abstract) != 0); ASSERT.CONSISTENCY_CHECK((methodHandle.GetAttributes() & MethodAttributes.Virtual) != 0); #region Calculate Binding Flags MethodAttributes methodAttributes = methodHandle.GetAttributes(); bool isPublic = (methodAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; bool isStatic = (methodAttributes & MethodAttributes.Static) != 0; bool isInherited = false; BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic); #endregion if ((methodAttributes & MethodAttributes.RTSpecialName) != 0 || methodHandle.IsILStub()) continue; // if it is an instantiated type get the InstantiatedMethodDesc if needed RuntimeMethodHandle instantiatedHandle = mayNeedInstantiatingStub ? methodHandle.GetInstantiatingStubIfNeeded(declaringTypeHandle) : methodHandle; RuntimeMethodInfo runtimeMethodInfo = new RuntimeMethodInfo( instantiatedHandle, declaringTypeHandle, m_runtimeTypeCache, methodAttributes, bindingFlags); list.Add(runtimeMethodInfo); #endregion } #endregion } else { #region IsClass or GenericParameter while(declaringTypeHandle.IsGenericVariable()) declaringTypeHandle = declaringTypeHandle.GetRuntimeType().BaseType.GetTypeHandleInternal(); bool* overrides = stackalloc bool[declaringTypeHandle.GetNumVirtuals()]; bool isValueType = declaringTypeHandle.GetRuntimeType().IsValueType; while(!declaringTypeHandle.IsNullHandle()) { bool mayNeedInstantiatingStub = declaringTypeHandle.HasInstantiation() && !declaringTypeHandle.IsGenericTypeDefinition(); int vtableSlots = declaringTypeHandle.GetNumVirtuals(); foreach (RuntimeMethodHandle methodHandle in declaringTypeHandle.IntroducedMethods) { if (!filter.Match(methodHandle.GetUtf8Name())) continue; #region Loop through all methods on the current type ASSERT.CONSISTENCY_CHECK(!methodHandle.IsNullHandle()); MethodAttributes methodAttributes = methodHandle.GetAttributes(); MethodAttributes methodAccess = methodAttributes & MethodAttributes.MemberAccessMask; #region Continue if this is a constructor ASSERT.CONSISTENCY_CHECK( LOGIC.IMPLIES((methodHandle.GetAttributes() & MethodAttributes.RTSpecialName) != 0, methodHandle.GetName().Equals(".ctor") || methodHandle.GetName().Equals(".cctor") || methodHandle.GetName().Equals("IL_STUB") )); if ((methodAttributes & MethodAttributes.RTSpecialName) != 0 || methodHandle.IsILStub()) continue; #endregion #region Continue if this is a private declared on a base type bool isVirtual = false; int methodSlot = 0; if ((methodAttributes & MethodAttributes.Virtual) != 0) { // only virtual if actually in the vtableslot range, but GetSlot will // assertt if an EnC method, which can't be virtual, so narrow down first // before calling GetSlot methodSlot = methodHandle.GetSlot(); isVirtual = (methodSlot < vtableSlots); } bool isPrivate = methodAccess == MethodAttributes.Private; bool isPrivateVirtual = isVirtual & isPrivate; bool isInherited = declaringTypeHandle.Value != ReflectedTypeHandle.Value; if (isInherited && isPrivate && !isPrivateVirtual) continue; #endregion #region Continue if this is a virtual and is already overridden if (isVirtual) { ASSERT.CONSISTENCY_CHECK( (methodAttributes & MethodAttributes.Abstract) != 0 || (methodAttributes & MethodAttributes.Virtual) != 0 || methodHandle.GetDeclaringType().Value != declaringTypeHandle.Value); if (overrides[methodSlot] == true) continue; overrides[methodSlot] = true; } else if (isValueType) { if ((methodAttributes & (MethodAttributes.Virtual | MethodAttributes.Abstract)) != 0) continue; } else { ASSERT.CONSISTENCY_CHECK((methodAttributes & (MethodAttributes.Virtual | MethodAttributes.Abstract)) == 0); } #endregion #region Calculate Binding Flags bool isPublic = methodAccess == MethodAttributes.Public; bool isStatic = (methodAttributes & MethodAttributes.Static) != 0; BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic); #endregion // if it is an instantiated type get the InstantiatedMethodDesc if needed RuntimeMethodHandle instantiatedHandle = mayNeedInstantiatingStub ? methodHandle.GetInstantiatingStubIfNeeded(declaringTypeHandle) : methodHandle; RuntimeMethodInfo runtimeMethodInfo = new RuntimeMethodInfo( instantiatedHandle, declaringTypeHandle, m_runtimeTypeCache, methodAttributes, bindingFlags); list.Add(runtimeMethodInfo); #endregion } declaringTypeHandle = declaringTypeHandle.GetBaseTypeHandle(); } #endregion } return list; } private List PopulateConstructors(Filter filter) { List list = new List (); if (ReflectedType.IsGenericParameter) { return list; } RuntimeTypeHandle declaringTypeHandle = ReflectedTypeHandle; bool mayNeedInstantiatingStub = declaringTypeHandle.HasInstantiation() && !declaringTypeHandle.IsGenericTypeDefinition(); foreach (RuntimeMethodHandle methodHandle in declaringTypeHandle.IntroducedMethods) { if (!filter.Match(methodHandle.GetUtf8Name())) continue; MethodAttributes methodAttributes = methodHandle.GetAttributes(); ASSERT.CONSISTENCY_CHECK(!methodHandle.IsNullHandle()); /* ASSERT.CONSISTENCY_ */ if ((methodAttributes & MethodAttributes.RTSpecialName) == 0) continue; if (methodHandle.IsILStub()) continue; // Constructors should not be virtual or abstract ASSERT.CONSISTENCY_CHECK( (methodAttributes & MethodAttributes.Abstract) == 0 && (methodAttributes & MethodAttributes.Virtual) == 0); #region Calculate Binding Flags bool isPublic = (methodAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; bool isStatic = (methodAttributes & MethodAttributes.Static) != 0; bool isInherited = false; BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic); #endregion // if it is an instantiated type get the InstantiatedMethodDesc if needed RuntimeMethodHandle instantiatedHandle = mayNeedInstantiatingStub ? methodHandle.GetInstantiatingStubIfNeeded(declaringTypeHandle) : methodHandle; RuntimeConstructorInfo runtimeConstructorInfo = new RuntimeConstructorInfo(instantiatedHandle, ReflectedTypeHandle, m_runtimeTypeCache, methodAttributes, bindingFlags); list.Add(runtimeConstructorInfo); } return list; } private unsafe List PopulateFields(Filter filter) { List list = new List (); RuntimeTypeHandle declaringTypeHandle = ReflectedTypeHandle; #region Populate all static, instance and literal fields while(declaringTypeHandle.IsGenericVariable()) declaringTypeHandle = declaringTypeHandle.GetRuntimeType().BaseType.GetTypeHandleInternal(); while(!declaringTypeHandle.IsNullHandle()) { PopulateRtFields(filter, declaringTypeHandle, list); PopulateLiteralFields(filter, declaringTypeHandle, list); declaringTypeHandle = declaringTypeHandle.GetBaseTypeHandle(); } #endregion #region Populate Literal Fields on Interfaces if (ReflectedType.IsGenericParameter) { Type[] interfaces = ReflectedTypeHandle.GetRuntimeType().BaseType.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { // Populate literal fields defined on any of the interfaces implemented by the declaring type PopulateLiteralFields(filter, interfaces[i].GetTypeHandleInternal(), list); PopulateRtFields(filter, interfaces[i].GetTypeHandleInternal(), list); } } else { RuntimeTypeHandle[] interfaces = ReflectedTypeHandle.GetInterfaces(); if (interfaces != null) { for (int i = 0; i < interfaces.Length; i++) { // Populate literal fields defined on any of the interfaces implemented by the declaring type PopulateLiteralFields(filter, interfaces[i], list); PopulateRtFields(filter, interfaces[i], list); } } } #endregion return list; } private unsafe void PopulateRtFields(Filter filter, RuntimeTypeHandle declaringTypeHandle, List list) { int** pResult = stackalloc int*[64]; int count = 64; if (!declaringTypeHandle.GetFields(pResult, &count)) { fixed(int** pBigResult = new int*[count]) { declaringTypeHandle.GetFields(pBigResult, &count); PopulateRtFields(filter, pBigResult, count, declaringTypeHandle, list); } } else if (count > 0) { PopulateRtFields(filter, pResult, count, declaringTypeHandle, list); } } private unsafe void PopulateRtFields(Filter filter, int** ppFieldHandles, int count, RuntimeTypeHandle declaringTypeHandle, List list) { ASSERT.PRECONDITION(!declaringTypeHandle.IsNullHandle()); ASSERT.PRECONDITION(!ReflectedTypeHandle.IsNullHandle()); bool needsStaticFieldForGeneric = declaringTypeHandle.HasInstantiation() && !declaringTypeHandle.ContainsGenericVariables(); bool isInherited = !declaringTypeHandle.Equals(ReflectedTypeHandle); for(int i = 0; i < count; i ++) { RuntimeFieldHandle runtimeFieldHandle = new RuntimeFieldHandle(ppFieldHandles[i]); if (!filter.Match(runtimeFieldHandle.GetUtf8Name())) continue; ASSERT.CONSISTENCY_CHECK(!runtimeFieldHandle.IsNullHandle()); FieldAttributes fieldAttributes = runtimeFieldHandle.GetAttributes(); FieldAttributes fieldAccess = fieldAttributes & FieldAttributes.FieldAccessMask; if (isInherited) { if (fieldAccess == FieldAttributes.Private) continue; } #region Calculate Binding Flags bool isPublic = fieldAccess == FieldAttributes.Public; bool isStatic = (fieldAttributes & FieldAttributes.Static) != 0; BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic); #endregion // correct the FieldDesc if needed if (needsStaticFieldForGeneric && isStatic) runtimeFieldHandle = runtimeFieldHandle.GetStaticFieldForGenericType(declaringTypeHandle); RuntimeFieldInfo runtimeFieldInfo = new RtFieldInfo(runtimeFieldHandle, declaringTypeHandle.GetRuntimeType(), m_runtimeTypeCache, bindingFlags); list.Add(runtimeFieldInfo); } } private unsafe void PopulateLiteralFields(Filter filter, RuntimeTypeHandle declaringTypeHandle, List list) { ASSERT.PRECONDITION(!declaringTypeHandle.IsNullHandle()); ASSERT.PRECONDITION(!ReflectedTypeHandle.IsNullHandle()); int tkDeclaringType = declaringTypeHandle.GetToken(); // Our policy is that TypeDescs do not have metadata tokens if (MdToken.IsNullToken(tkDeclaringType)) return; MetadataImport scope = declaringTypeHandle.GetModuleHandle().GetMetadataImport(); int cFields = scope.EnumFieldsCount(tkDeclaringType); int* tkFields = stackalloc int[cFields]; scope.EnumFields(tkDeclaringType, tkFields, cFields); for (int i = 0; i < cFields; i++) { int tkField = tkFields[i]; ASSERT.PRECONDITION(MdToken.IsTokenOfType(tkField, MetadataTokenType.FieldDef)); ASSERT.PRECONDITION(!MdToken.IsNullToken(tkField)); Utf8String name; name = scope.GetName(tkField); if (!filter.Match(name)) continue; FieldAttributes fieldAttributes; scope.GetFieldDefProps(tkField, out fieldAttributes); FieldAttributes fieldAccess = fieldAttributes & FieldAttributes.FieldAccessMask; if ((fieldAttributes & FieldAttributes.Literal) != 0) { bool isInherited = !declaringTypeHandle.Equals(ReflectedTypeHandle); if (isInherited) { bool isPrivate = fieldAccess == FieldAttributes.Private; if (isPrivate) continue; } #region Calculate Binding Flags bool isPublic = fieldAccess == FieldAttributes.Public; bool isStatic = (fieldAttributes & FieldAttributes.Static) != 0; BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic); #endregion RuntimeFieldInfo runtimeFieldInfo = new MdFieldInfo(tkField, fieldAttributes, declaringTypeHandle, m_runtimeTypeCache, bindingFlags); list.Add(runtimeFieldInfo); } } } private static void AddElementTypes(Type template, IList types) { if (!template.HasElementType) return; AddElementTypes(template.GetElementType(), types); for (int i = 0; i < types.Count; i ++) { if (template.IsArray) { if (template.IsSzArray) types[i] = types[i].MakeArrayType(); else types[i] = types[i].MakeArrayType(template.GetArrayRank()); } else if (template.IsPointer) { types[i] = types[i].MakePointerType(); } } } private List PopulateInterfaces(Filter filter) { List list = new List (); RuntimeTypeHandle declaringTypeHandle = ReflectedTypeHandle; if (!declaringTypeHandle.IsGenericVariable()) { RuntimeTypeHandle[] ifaces = ReflectedTypeHandle.GetInterfaces(); if (ifaces != null) { for (int i = 0; i < ifaces.Length; i++) { RuntimeType interfaceType = ifaces[i].GetRuntimeType(); if (!filter.Match(interfaceType.GetTypeHandleInternal().GetUtf8Name())) continue; ASSERT.CONSISTENCY_CHECK(interfaceType.IsInterface); list.Add(interfaceType); } } if (ReflectedType.IsSzArray) { Type arrayType = ReflectedType.GetElementType(); if (!arrayType.IsPointer) { Type iList = typeof(IList<>).MakeGenericType(arrayType); if (iList.IsAssignableFrom(ReflectedType)) { if (filter.Match(iList.GetTypeHandleInternal().GetUtf8Name())) list.Add(iList as RuntimeType); Type[] iFaces = iList.GetInterfaces(); for(int j = 0; j < iFaces.Length; j++) { Type iFace = iFaces[j]; if (iFace.IsGenericType && filter.Match(iFace.GetTypeHandleInternal().GetUtf8Name())) list.Add(iFaces[j] as RuntimeType); } } } } } else { List al = new List (); // Get all constraints Type[] constraints = declaringTypeHandle.GetRuntimeType().GetGenericParameterConstraints(); // Populate transitive closure of all interfaces in constraint set for (int i = 0; i < constraints.Length; i++) { Type constraint = constraints[i]; if (constraint.IsInterface) al.Add(constraint as RuntimeType); Type[] temp = constraint.GetInterfaces(); for (int j = 0; j < temp.Length; j++) al.Add(temp[j] as RuntimeType); } // Remove duplicates Hashtable ht = new Hashtable(); for (int i = 0; i < al.Count; i++) { Type constraint = al[i] as Type; if (!ht.Contains(constraint)) ht[constraint] = constraint; } Type[] interfaces = new Type[ht.Values.Count]; ht.Values.CopyTo(interfaces, 0); // Populate link-list for (int i = 0; i < interfaces.Length; i++) { if (!filter.Match(interfaces[i].GetTypeHandleInternal().GetUtf8Name())) continue; list.Add(interfaces[i] as RuntimeType); } } return list; } private unsafe List PopulateNestedClasses(Filter filter) { List list = new List (); RuntimeTypeHandle declaringTypeHandle = ReflectedTypeHandle; if (declaringTypeHandle.IsGenericVariable()) { while(declaringTypeHandle.IsGenericVariable()) declaringTypeHandle = declaringTypeHandle.GetRuntimeType().BaseType.GetTypeHandleInternal(); } int tkEnclosingType = declaringTypeHandle.GetToken(); // For example, TypeDescs do not have metadata tokens if (MdToken.IsNullToken(tkEnclosingType)) return list; ModuleHandle moduleHandle = declaringTypeHandle.GetModuleHandle(); MetadataImport scope = moduleHandle.GetMetadataImport(); int cNestedClasses = scope.EnumNestedTypesCount(tkEnclosingType); int* tkNestedClasses = stackalloc int[cNestedClasses]; scope.EnumNestedTypes(tkEnclosingType, tkNestedClasses, cNestedClasses); for (int i = 0; i < cNestedClasses; i++) { RuntimeTypeHandle nestedTypeHandle = new RuntimeTypeHandle(); try { nestedTypeHandle = moduleHandle.ResolveTypeHandle(tkNestedClasses[i]); } catch(System.TypeLoadException) { // In a reflection emit scenario, we may have a token for a class which // has not been baked and hence cannot be loaded. continue; } if (!filter.Match(nestedTypeHandle.GetRuntimeType().GetTypeHandleInternal().GetUtf8Name())) continue; list.Add(nestedTypeHandle.GetRuntimeType()); } return list; } private unsafe List PopulateEvents(Filter filter) { ASSERT.PRECONDITION(!ReflectedTypeHandle.IsNullHandle()); Hashtable csEventInfos = new Hashtable(); RuntimeTypeHandle declaringTypeHandle = ReflectedTypeHandle; List list = new List (); bool isInterface = (declaringTypeHandle.GetAttributes() & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface; if (!isInterface) { while(declaringTypeHandle.IsGenericVariable()) declaringTypeHandle = declaringTypeHandle.GetRuntimeType().BaseType.GetTypeHandleInternal(); // Populate associates off of the class hierarchy while(!declaringTypeHandle.IsNullHandle()) { PopulateEvents(filter, declaringTypeHandle, csEventInfos, list); declaringTypeHandle = declaringTypeHandle.GetBaseTypeHandle(); } } else { // Populate associates for this interface PopulateEvents(filter, declaringTypeHandle, csEventInfos, list); } return list; } private unsafe void PopulateEvents( Filter filter, RuntimeTypeHandle declaringTypeHandle, Hashtable csEventInfos, List list) { int tkDeclaringType = declaringTypeHandle.GetToken(); // Arrays, Pointers, ByRef types and others generated only the fly by the RT do not have tokens. if (MdToken.IsNullToken(tkDeclaringType)) return; MetadataImport scope = declaringTypeHandle.GetModuleHandle().GetMetadataImport(); int cEvents = scope.EnumEventsCount(tkDeclaringType); int* tkEvents = stackalloc int[cEvents]; scope.EnumEvents(tkDeclaringType, tkEvents, cEvents); PopulateEvents(filter, declaringTypeHandle, scope, tkEvents, cEvents, csEventInfos, list); } private unsafe void PopulateEvents(Filter filter, RuntimeTypeHandle declaringTypeHandle, MetadataImport scope, int* tkAssociates, int cAssociates, Hashtable csEventInfos, List list) { for (int i = 0; i < cAssociates; i++) { int tkAssociate = tkAssociates[i]; bool isPrivate; ASSERT.PRECONDITION(!MdToken.IsNullToken(tkAssociate)); ASSERT.PRECONDITION(MdToken.IsTokenOfType(tkAssociate, MetadataTokenType.Event)); Utf8String name; name = scope.GetName(tkAssociate); if (!filter.Match(name)) continue; RuntimeEventInfo eventInfo = new RuntimeEventInfo( tkAssociate, declaringTypeHandle.GetRuntimeType() as RuntimeType, m_runtimeTypeCache, out isPrivate); #region Remove Inherited Privates if (!declaringTypeHandle.Equals(m_runtimeTypeCache.RuntimeTypeHandle) && isPrivate) continue; #endregion #region Remove Duplicates if (csEventInfos[eventInfo.Name] != null) continue; csEventInfos[eventInfo.Name] = eventInfo; #endregion list.Add(eventInfo); } } private unsafe List PopulateProperties(Filter filter) { ASSERT.PRECONDITION(!ReflectedTypeHandle.IsNullHandle()); ASSERT.CONSISTENCY_CHECK(m_csMemberInfos == null); Hashtable csPropertyInfos = new Hashtable(); RuntimeTypeHandle declaringTypeHandle = ReflectedTypeHandle; List list = new List (); bool isInterface = (declaringTypeHandle.GetAttributes() & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface; if (!isInterface) { while(declaringTypeHandle.IsGenericVariable()) declaringTypeHandle = declaringTypeHandle.GetRuntimeType().BaseType.GetTypeHandleInternal(); // Populate associates off of the class hierarchy while(!declaringTypeHandle.IsNullHandle()) { PopulateProperties(filter, declaringTypeHandle, csPropertyInfos, list); declaringTypeHandle = declaringTypeHandle.GetBaseTypeHandle(); } } else { // Populate associates for this interface PopulateProperties(filter, declaringTypeHandle, csPropertyInfos, list); } return list; } private unsafe void PopulateProperties(Filter filter, RuntimeTypeHandle declaringTypeHandle, Hashtable csPropertyInfos, List list) { int tkDeclaringType = declaringTypeHandle.GetToken(); // Arrays, Pointers, ByRef types and others generated only the fly by the RT do not have tokens. if (MdToken.IsNullToken(tkDeclaringType)) return; MetadataImport scope = declaringTypeHandle.GetModuleHandle().GetMetadataImport(); int cProperties = scope.EnumPropertiesCount(tkDeclaringType); int* tkProperties = stackalloc int[cProperties]; scope.EnumProperties(tkDeclaringType, tkProperties, cProperties); PopulateProperties(filter, declaringTypeHandle, tkProperties, cProperties, csPropertyInfos, list); } private unsafe void PopulateProperties(Filter filter, RuntimeTypeHandle declaringTypeHandle, int* tkAssociates, int cProperties, Hashtable csPropertyInfos, List list) { for(int i = 0; i < cProperties; i ++) { int tkAssociate = tkAssociates[i]; bool isPrivate; ASSERT.PRECONDITION(!MdToken.IsNullToken(tkAssociate)); ASSERT.PRECONDITION(MdToken.IsTokenOfType(tkAssociate, MetadataTokenType.Property)); Utf8String name; name = declaringTypeHandle.GetRuntimeType().Module.MetadataImport.GetName(tkAssociate); if (!filter.Match(name)) continue; RuntimePropertyInfo propertyInfo = new RuntimePropertyInfo( tkAssociate, declaringTypeHandle.GetRuntimeType() as RuntimeType, m_runtimeTypeCache, out isPrivate); #region Remove Privates if (!declaringTypeHandle.Equals(m_runtimeTypeCache.RuntimeTypeHandle) && isPrivate) continue; #endregion #region Remove Duplicates List cache = csPropertyInfos[propertyInfo.Name] as List ; if (cache == null) { cache = new List (); csPropertyInfos[propertyInfo.Name] = cache; } else { for (int j = 0; j < cache.Count; j ++) { if (propertyInfo.EqualsSig(cache[j])) { cache = null; break; } } } if (cache == null) continue; cache.Add(propertyInfo); #endregion list.Add(propertyInfo); } } #endregion #region NonPrivate Members internal CerArrayList GetMemberList(MemberListType listType, string name, CacheType cacheType) { CerArrayList list = null; switch(listType) { case MemberListType.CaseSensitive: if (m_csMemberInfos == null) { return Populate(name, listType, cacheType); } else { list = m_csMemberInfos[name]; if (list == null) return Populate(name, listType, cacheType); return list; } case MemberListType.All: if (m_cacheComplete) return m_root; return Populate(null, listType, cacheType); default: if (m_cisMemberInfos == null) { return Populate(name, listType, cacheType); } else { list = m_cisMemberInfos[name]; if (list == null) return Populate(name, listType, cacheType); return list; } } } internal RuntimeTypeHandle ReflectedTypeHandle { get { return m_runtimeTypeCache.RuntimeTypeHandle; } } internal RuntimeType ReflectedType { get { return ReflectedTypeHandle.GetRuntimeType(); } } #endregion } #endregion #region Private Data Members private WhatsCached m_whatsCached; private RuntimeTypeHandle m_runtimeTypeHandle; private RuntimeType m_runtimeType; private RuntimeType m_enclosingType; private TypeCode m_typeCode; private string m_name, m_fullname, m_toString, m_namespace; private bool m_isGlobal; private bool m_bIsDomainInitialized; private MemberInfoCache m_methodInfoCache; private MemberInfoCache m_constructorInfoCache; private MemberInfoCache m_fieldInfoCache; private MemberInfoCache m_interfaceCache; private MemberInfoCache m_nestedClassesCache; private MemberInfoCache m_propertyInfoCache; private MemberInfoCache m_eventInfoCache; private static CerHashtable s_methodInstantiations; private static bool s_dontrunhack = false; #endregion #region Constructor internal RuntimeTypeCache(RuntimeType runtimeType) { m_typeCode = TypeCode.Empty; m_runtimeType = runtimeType; m_runtimeTypeHandle = runtimeType.GetTypeHandleInternal(); m_isGlobal = m_runtimeTypeHandle.GetModuleHandle().GetModuleTypeHandle().Equals(m_runtimeTypeHandle); s_dontrunhack = true; Prejitinit_HACK(); } #endregion #region Private Members private string ConstructName(ref string name, bool nameSpace, bool fullinst, bool assembly) { if (name == null) { name = RuntimeTypeHandle.ConstructName(nameSpace, fullinst, assembly); } return name; } private CerArrayList GetMemberList (ref MemberInfoCache m_cache, MemberListType listType, string name, CacheType cacheType) where T : MemberInfo { MemberInfoCache existingCache = GetMemberCache (ref m_cache); return existingCache.GetMemberList(listType, name, cacheType); } private MemberInfoCache GetMemberCache (ref MemberInfoCache m_cache) where T : MemberInfo { MemberInfoCache existingCache = m_cache; if (existingCache == null) { MemberInfoCache newCache = new MemberInfoCache (this); existingCache = Interlocked.CompareExchange(ref m_cache, newCache, null); if (existingCache == null) existingCache = newCache; } return existingCache; } #endregion #region Internal Members internal bool DomainInitialized { get { return m_bIsDomainInitialized; } set { m_bIsDomainInitialized = value; } } internal string GetName() { return ConstructName(ref m_name, false, false, false); } internal unsafe string GetNameSpace() { // @Optimization - Use ConstructName to populate m_namespace if (m_namespace == null) { Type type = m_runtimeType; type = type.GetRootElementType(); while (type.IsNested) type = type.DeclaringType; m_namespace = type.GetTypeHandleInternal().GetModuleHandle( ).GetMetadataImport().GetNamespace(type.MetadataToken).ToString(); } return m_namespace; } internal string GetToString() { return ConstructName(ref m_toString, true, false, false); } internal string GetFullName() { if (!m_runtimeType.IsGenericTypeDefinition && m_runtimeType.ContainsGenericParameters) return null; return ConstructName(ref m_fullname, true, true, false); } internal TypeCode TypeCode { get { return m_typeCode; } set { m_typeCode = value; } } internal unsafe RuntimeType GetEnclosingType() { if ((m_whatsCached & WhatsCached.EnclosingType) == 0) { m_enclosingType = RuntimeTypeHandle.GetDeclaringType().GetRuntimeType(); m_whatsCached |= WhatsCached.EnclosingType; } return m_enclosingType; } internal bool IsGlobal { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { return m_isGlobal; } } internal RuntimeType RuntimeType { get { return m_runtimeType; } } internal RuntimeTypeHandle RuntimeTypeHandle { get { return m_runtimeTypeHandle; } } internal void InvalidateCachedNestedType() { m_nestedClassesCache = null; } #endregion #region Caches Accessors internal MethodInfo GetGenericMethodInfo(RuntimeMethodHandle genericMethod) { if (s_methodInstantiations == null) Interlocked.CompareExchange(ref s_methodInstantiations, new CerHashtable (), null); RuntimeMethodInfo rmi = new RuntimeMethodInfo( genericMethod, genericMethod.GetDeclaringType(), this, genericMethod.GetAttributes(), (BindingFlags)(-1)); RuntimeMethodInfo crmi = null; crmi = s_methodInstantiations[rmi]; if (crmi != null) return crmi; bool lockTaken = false; bool preallocationComplete = false; RuntimeHelpers.PrepareConstrainedRegions(); try { Monitor.ReliableEnter(s_methodInstantiations, ref lockTaken); crmi = s_methodInstantiations[rmi]; if (crmi != null) return crmi; s_methodInstantiations.Preallocate(1); preallocationComplete = true; } finally { if (preallocationComplete) { s_methodInstantiations[rmi] = rmi; } if (lockTaken) { Monitor.Exit(s_methodInstantiations); } } return rmi; } internal CerArrayList GetMethodList(MemberListType listType, string name) { return GetMemberList (ref m_methodInfoCache, listType, name, CacheType.Method); } internal CerArrayList GetConstructorList(MemberListType listType, string name) { return GetMemberList (ref m_constructorInfoCache, listType, name, CacheType.Constructor); } internal CerArrayList GetPropertyList(MemberListType listType, string name) { return GetMemberList (ref m_propertyInfoCache, listType, name, CacheType.Property); } internal CerArrayList GetEventList(MemberListType listType, string name) { return GetMemberList (ref m_eventInfoCache, listType, name, CacheType.Event); } internal CerArrayList GetFieldList(MemberListType listType, string name) { return GetMemberList (ref m_fieldInfoCache, listType, name, CacheType.Field); } internal CerArrayList GetInterfaceList(MemberListType listType, string name) { return GetMemberList (ref m_interfaceCache, listType, name, CacheType.Interface); } internal CerArrayList GetNestedTypeList(MemberListType listType, string name) { return GetMemberList (ref m_nestedClassesCache, listType, name, CacheType.NestedType); } internal MethodBase GetMethod(RuntimeTypeHandle declaringType, RuntimeMethodHandle method) { GetMemberCache (ref m_methodInfoCache); return m_methodInfoCache.AddMethod(declaringType, method, CacheType.Method); } internal MethodBase GetConstructor(RuntimeTypeHandle declaringType, RuntimeMethodHandle constructor) { GetMemberCache (ref m_constructorInfoCache); return m_constructorInfoCache.AddMethod(declaringType, constructor, CacheType.Constructor); } internal FieldInfo GetField(RuntimeFieldHandle field) { GetMemberCache (ref m_fieldInfoCache); return m_fieldInfoCache.AddField(field); } #endregion } #endregion #region Static Members #region Internal [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern void PrepareMemberInfoCache(RuntimeTypeHandle rt); internal static MethodBase GetMethodBase(ModuleHandle scope, int typeMetadataToken) { return GetMethodBase(scope.ResolveMethodHandle(typeMetadataToken)); } internal static MethodBase GetMethodBase(Module scope, int typeMetadataToken) { return GetMethodBase(scope.GetModuleHandle(), typeMetadataToken); } internal static MethodBase GetMethodBase(RuntimeMethodHandle methodHandle) { return GetMethodBase(RuntimeTypeHandle.EmptyHandle, methodHandle); } internal unsafe static MethodBase GetMethodBase(RuntimeTypeHandle reflectedTypeHandle, RuntimeMethodHandle methodHandle) { ASSERT.CONSISTENCY_CHECK(!reflectedTypeHandle.IsNullHandle()); ASSERT.CONSISTENCY_CHECK(!methodHandle.IsNullHandle()); if (methodHandle.IsDynamicMethod()) { Resolver resolver = methodHandle.GetResolver(); if (resolver != null) return resolver.GetDynamicMethod(); return null; } // verify the type/method relationship Type declaredType = methodHandle.GetDeclaringType().GetRuntimeType(); RuntimeType reflectedType = reflectedTypeHandle.GetRuntimeType(); RuntimeTypeHandle[] methodInstantiation = null; bool fNeedInstantiatingStub = false; if (reflectedType == null) reflectedType = declaredType as RuntimeType; if (reflectedType.IsArray) { MethodBase[] methodBases = reflectedType.GetMember( methodHandle.GetName(), MemberTypes.Constructor | MemberTypes.Method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) as MethodBase[]; bool loaderAssuredCompatible = false; for (int i = 0; i < methodBases.Length; i ++) { if (methodBases[i].GetMethodHandle() == methodHandle) loaderAssuredCompatible = true; } if (!loaderAssuredCompatible) throw new ArgumentException(String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveMethodHandle"), reflectedType.ToString(), declaredType.ToString())); declaredType = reflectedType; } else if (!declaredType.IsAssignableFrom(reflectedType)) { if (!declaredType.IsGenericType) throw new ArgumentException(String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveMethodHandle"), reflectedType.ToString(), declaredType.ToString())); // ignoring instantiation is the ReflectedType a subtype of the DeclaringType Type declaringDefinition = declaredType.GetGenericTypeDefinition(); Type baseType = reflectedType; while (baseType != null) { Type baseDefinition = baseType; if (baseDefinition.IsGenericType && !baseType.IsGenericTypeDefinition) baseDefinition = baseDefinition.GetGenericTypeDefinition(); if (baseDefinition.Equals(declaringDefinition)) break; baseType = baseType.BaseType; } if (baseType == null) { // ignoring instantiation is the ReflectedType is not a subtype of the DeclaringType throw new ArgumentException(String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveMethodHandle"), reflectedType.ToString(), declaredType.ToString())); } // remap the method to same method on the subclass ReflectedType declaredType = baseType; methodInstantiation = methodHandle.GetMethodInstantiation(); bool bIsGenericMethodDefinition = methodHandle.IsGenericMethodDefinition(); // lookup via v-table slot the RuntimeMethodHandle on the new declaring type methodHandle = methodHandle.GetMethodFromCanonical(declaredType.GetTypeHandleInternal()); // if the original methodHandle was the definition then we don't need to rebind generic method arguments // because all RuntimeMethodHandles retrieved off of the canonical method table are definitions. That's // why for everything else we need to rebind the generic method arguments. if (!bIsGenericMethodDefinition) { fNeedInstantiatingStub = true; } } if (declaredType.IsValueType) methodHandle = methodHandle.GetUnboxingStub(); if ( fNeedInstantiatingStub || ( declaredType.GetTypeHandleInternal().HasInstantiation() && !declaredType.GetTypeHandleInternal().IsGenericTypeDefinition() && !methodHandle.HasMethodInstantiation())) { // if declaredType is an instantiated type and methodHandle is not generic get the instantiated MethodDesc (if needed) // MemberInfoCache .PopulateMethods and MemberInfoCache .PopulateConstructors do this already methodHandle = methodHandle.GetInstantiatingStub(declaredType.GetTypeHandleInternal(), methodInstantiation); } if (methodHandle.IsConstructor()) { // Constructor case: constructors cannot be generic return reflectedType.Cache.GetConstructor(declaredType.GetTypeHandleInternal(), methodHandle); } else { // Method case if (methodHandle.HasMethodInstantiation() && !methodHandle.IsGenericMethodDefinition()) return reflectedType.Cache.GetGenericMethodInfo(methodHandle); else return reflectedType.Cache.GetMethod(declaredType.GetTypeHandleInternal(), methodHandle); } } internal bool DomainInitialized { get { return Cache.DomainInitialized; } set { Cache.DomainInitialized = value; } } internal unsafe static FieldInfo GetFieldInfo(RuntimeFieldHandle fieldHandle) { return GetFieldInfo(fieldHandle.GetApproxDeclaringType(), fieldHandle); } internal unsafe static FieldInfo GetFieldInfo(RuntimeTypeHandle reflectedTypeHandle, RuntimeFieldHandle fieldHandle) { // verify the type/method relationship if (reflectedTypeHandle.IsNullHandle()) { reflectedTypeHandle = fieldHandle.GetApproxDeclaringType(); } else { RuntimeTypeHandle declaredTypeHandle = fieldHandle.GetApproxDeclaringType(); if (!reflectedTypeHandle.Equals(declaredTypeHandle)) { if (!fieldHandle.AcquiresContextFromThis() || !declaredTypeHandle.GetCanonicalHandle().Equals(reflectedTypeHandle.GetCanonicalHandle())) { throw new ArgumentException(String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveFieldHandle"), reflectedTypeHandle.GetRuntimeType().ToString(), declaredTypeHandle.GetRuntimeType().ToString())); } } } return reflectedTypeHandle.GetRuntimeType().Cache.GetField(fieldHandle); } // Called internally internal unsafe static PropertyInfo GetPropertyInfo(RuntimeTypeHandle reflectedTypeHandle, int tkProperty) { RuntimePropertyInfo property = null; CerArrayList candidates = reflectedTypeHandle.GetRuntimeType().Cache.GetPropertyList(MemberListType.All, null); for (int i = 0; i < candidates.Count; i++) { property = candidates[i]; if (property.MetadataToken == tkProperty) return property; } ASSERT.UNREACHABLE(); throw new SystemException(); } private static void ThrowIfTypeNeverValidGenericArgument(Type type) { if (type.IsPointer || type.IsByRef || type == typeof(void)) throw new ArgumentException( String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_NeverValidGenericArgument"), type.ToString())); } internal static void SanityCheckGenericArguments(Type[] genericArguments, Type[] genericParamters) { if (genericArguments == null) throw new ArgumentNullException(); for(int i = 0; i < genericArguments.Length; i++) { if (genericArguments[i] == null) throw new ArgumentNullException(); ThrowIfTypeNeverValidGenericArgument(genericArguments[i]); } if (genericArguments.Length != genericParamters.Length) throw new ArgumentException( String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_NotEnoughGenArguments", genericArguments.Length, genericParamters.Length))); } internal static void ValidateGenericArguments(MemberInfo definition, Type[] genericArguments, Exception e) { RuntimeTypeHandle[] typeContextHandle = null; RuntimeTypeHandle[] methodContextHandle = null; Type[] genericParamters = null; if (definition is Type) { Type genericTypeDefinition = (Type)definition; genericParamters = genericTypeDefinition.GetGenericArguments(); typeContextHandle = new RuntimeTypeHandle[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i ++) typeContextHandle[i] = genericArguments[i].GetTypeHandleInternal(); } else { MethodInfo genericMethodDefinition = (MethodInfo)definition; genericParamters = genericMethodDefinition.GetGenericArguments(); methodContextHandle = new RuntimeTypeHandle[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i ++) methodContextHandle[i] = genericArguments[i].GetTypeHandleInternal(); Type declaringType = genericMethodDefinition.DeclaringType; if (declaringType != null) typeContextHandle = declaringType.GetTypeHandleInternal().GetInstantiation(); } for (int i = 0; i < genericArguments.Length; i++) { Type genericArgument = genericArguments[i]; Type genericParameter = genericParamters[i]; if (!genericParameter.GetTypeHandleInternal().SatisfiesConstraints( typeContextHandle, methodContextHandle, genericArgument.GetTypeHandleInternal())) { throw new ArgumentException( String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_GenConstraintViolation"), i.ToString(CultureInfo.CurrentCulture), genericArgument.ToString(), definition.ToString(), genericParameter.ToString()), e); } } } private static void SplitName(string fullname, out string name, out string ns) { name = null; ns = null; if (fullname == null) return; // Get namespace int nsDelimiter = fullname.LastIndexOf(".", StringComparison.Ordinal); if (nsDelimiter != -1 ) { ns = fullname.Substring(0, nsDelimiter); int nameLength = fullname.Length - ns.Length - 1; if (nameLength != 0) name = fullname.Substring(nsDelimiter + 1, nameLength); else name = ""; ASSERT.CONSISTENCY_CHECK(fullname.Equals(ns + "." + name)); } else { name = fullname; } } #endregion #region Filters internal static BindingFlags FilterPreCalculate(bool isPublic, bool isInherited, bool isStatic) { BindingFlags bindingFlags = isPublic ? BindingFlags.Public : BindingFlags.NonPublic; if (isInherited) { // We arrange things so the DeclaredOnly flag means "include inherited members" bindingFlags |= BindingFlags.DeclaredOnly; if (isStatic) { bindingFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy; } else { bindingFlags |= BindingFlags.Instance; } } else { if (isStatic) { bindingFlags |= BindingFlags.Static; } else { bindingFlags |= BindingFlags.Instance; } } return bindingFlags; } private static void FilterHelper( BindingFlags bindingFlags, ref string name, bool allowPrefixLookup, out bool prefixLookup, out bool ignoreCase, out MemberListType listType) { prefixLookup = false; ignoreCase = false; if (name != null) { if ((bindingFlags & BindingFlags.IgnoreCase) != 0) { name = name.ToLower(CultureInfo.InvariantCulture); ignoreCase = true; listType = MemberListType.CaseInsensitive; } else { listType = MemberListType.CaseSensitive; } if (allowPrefixLookup && name.EndsWith("*", StringComparison.Ordinal)) { name = name.Substring(0, name.Length - 1); prefixLookup = true; listType = MemberListType.All; } } else { listType = MemberListType.All; } } private static void FilterHelper(BindingFlags bindingFlags, ref string name, out bool ignoreCase, out MemberListType listType) { bool prefixLookup; FilterHelper(bindingFlags, ref name, false, out prefixLookup, out ignoreCase, out listType); } private static bool FilterApplyPrefixLookup(MemberInfo memberInfo, string name, bool ignoreCase) { ASSERT.CONSISTENCY_CHECK(name != null); if (ignoreCase) { if (!memberInfo.Name.ToLower(CultureInfo.InvariantCulture).StartsWith(name, StringComparison.Ordinal)) return false; } else { if (!memberInfo.Name.StartsWith(name, StringComparison.Ordinal)) return false; } return true; } private static bool FilterApplyBase( MemberInfo memberInfo, BindingFlags bindingFlags, bool isPublic, bool isNonProtectedInternal, bool isStatic, string name, bool prefixLookup) { #region Preconditions ASSERT.PRECONDITION(memberInfo != null); ASSERT.PRECONDITION(name == null || (bindingFlags & BindingFlags.IgnoreCase) == 0 || (name.ToLower(CultureInfo.InvariantCulture).Equals(name))); #endregion #region Filter by Public & Private if (isPublic) { if ((bindingFlags & BindingFlags.Public) == 0) return false; } else { if ((bindingFlags & BindingFlags.NonPublic) == 0) return false; } #endregion bool isInherited = memberInfo.DeclaringType != memberInfo.ReflectedType; #region Filter by DeclaredOnly if ((bindingFlags & BindingFlags.DeclaredOnly) != 0 && isInherited) return false; #endregion #region Filter by Static & Instance if (memberInfo.MemberType != MemberTypes.TypeInfo && memberInfo.MemberType != MemberTypes.NestedType) { if (isStatic) { if ((bindingFlags & BindingFlags.FlattenHierarchy) == 0 && isInherited) return false; if ((bindingFlags & BindingFlags.Static) == 0) return false; } else { if ((bindingFlags & BindingFlags.Instance) == 0) return false; } } #endregion #region Filter by name wrt prefixLookup and implicitly by case sensitivity if (prefixLookup == true) { if (!FilterApplyPrefixLookup(memberInfo, name, (bindingFlags & BindingFlags.IgnoreCase) != 0)) return false; } #endregion #region Asymmetries // @Asymmetry - Internal, inherited, instance, non-protected, non-virtual, non-abstract members returned // iff BindingFlags !DeclaredOnly, Instance and Public are present except for fields if (((bindingFlags & BindingFlags.DeclaredOnly) == 0) && // DeclaredOnly not present isInherited && // Is inherited Member (isNonProtectedInternal) && // Is non-protected internal member ((bindingFlags & BindingFlags.NonPublic) != 0) && // BindingFlag.NonPublic present (!isStatic) && // Is instance member ((bindingFlags & BindingFlags.Instance) != 0)) // BindingFlag.Instance present { MethodInfo methodInfo = memberInfo as MethodInfo; if (methodInfo == null) return false; if (!methodInfo.IsVirtual && !methodInfo.IsAbstract) return false; } #endregion return true; } private static bool FilterApplyType( Type type, BindingFlags bindingFlags, string name, bool prefixLookup, string ns) { ASSERT.PRECONDITION(type != null); ASSERT.PRECONDITION(type is RuntimeType); bool isPublic = type.IsNestedPublic || type.IsPublic; bool isStatic = false; if (!RuntimeType.FilterApplyBase(type, bindingFlags, isPublic, type.IsNestedAssembly, isStatic, name, prefixLookup)) return false; if (ns != null && !type.Namespace.Equals(ns)) return false; return true; } private static bool FilterApplyMethodBaseInfo( MethodBase methodBase, BindingFlags bindingFlags, string name, CallingConventions callConv, Type[] argumentTypes, bool prefixLookup) { ASSERT.PRECONDITION(methodBase != null); #region Apply Base Filter bindingFlags ^= BindingFlags.DeclaredOnly; BindingFlags matchFlags; RuntimeMethodInfo methodInfo = methodBase as RuntimeMethodInfo; if (methodInfo == null) { RuntimeConstructorInfo constructorInfo = methodBase as RuntimeConstructorInfo; matchFlags = constructorInfo.BindingFlags; } else { matchFlags = methodInfo.BindingFlags; } if ((bindingFlags & matchFlags) != matchFlags || (prefixLookup && !FilterApplyPrefixLookup(methodBase, name, (bindingFlags & BindingFlags.IgnoreCase) != 0))) return false; #endregion return FilterApplyMethodBaseInfo(methodBase, bindingFlags, callConv, argumentTypes); } private static bool FilterApplyMethodBaseInfo( MethodBase methodBase, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes) { #region Check CallingConvention if ((callConv & CallingConventions.Any) == 0) { if ((callConv & CallingConventions.VarArgs) != 0 && (methodBase.CallingConvention & CallingConventions.VarArgs) == 0) return false; if ((callConv & CallingConventions.Standard) != 0 && (methodBase.CallingConvention & CallingConventions.Standard) == 0) return false; } #endregion #region If argumentTypes supplied if (argumentTypes != null) { ParameterInfo[] parameterInfos = methodBase.GetParametersNoCopy(); if (argumentTypes.Length != parameterInfos.Length) { #region Invoke Member, Get\Set & Create Instance specific case // If the number of supplied arguments differs than the number in the signature AND // we are not filtering for a dynamic call -- InvokeMethod or CreateInstance -- filter out the method. if ((bindingFlags & (BindingFlags.InvokeMethod | BindingFlags.CreateInstance | BindingFlags.GetProperty | BindingFlags.SetProperty)) == 0) return false; bool testForParamArray = false; bool excessSuppliedArguments = argumentTypes.Length > parameterInfos.Length; if (excessSuppliedArguments) { // more supplied arguments than parameters, additional arguments could be vararg #region Varargs // If method is not vararg, additional arguments can not be passed as vararg if ((methodBase.CallingConvention & CallingConventions.VarArgs) == 0) { testForParamArray = true; } else { // If Binding flags did not include varargs we would have filtered this vararg method. // This Invariant established during callConv ASSERT.CONSISTENCY_CHECK((callConv & CallingConventions.VarArgs) != 0); } #endregion } else {// fewer supplied arguments than parameters, missing arguments could be optional #region OptionalParamBinding if ((bindingFlags & BindingFlags.OptionalParamBinding) == 0) { testForParamArray = true; } else { // From our existing code, our policy here is that if a parameterInfo // is optional then all subsequent parameterInfos shall be optional. // Thus, iff the first parameterInfo is not optional then this MethodInfo is no longer a canidate. if (!parameterInfos[argumentTypes.Length].IsOptional) testForParamArray = true; } #endregion } #region ParamArray if (testForParamArray) { if (parameterInfos.Length == 0) return false; // The last argument of the signature could be a param array. bool shortByMoreThanOneSuppliedArgument = argumentTypes.Length < parameterInfos.Length - 1; if (shortByMoreThanOneSuppliedArgument) return false; ParameterInfo lastParameter = parameterInfos[parameterInfos.Length - 1]; if (!lastParameter.ParameterType.IsArray) return false; if (!lastParameter.IsDefined(typeof(ParamArrayAttribute), false)) return false; } #endregion #endregion } else { #region Exact Binding if ((bindingFlags & BindingFlags.ExactBinding) != 0) { // Legacy behavior is to ignore ExactBinding when InvokeMember is specified. // Why filter by InvokeMember? If the answer is we leave this to the binder then why not leave // all the rest of this to the binder too? Further, what other semanitc would the binder // use for BindingFlags.ExactBinding besides this one? Further, why not include CreateInstance // in this if statement? That's just InvokeMethod with a constructor, right? if ((bindingFlags & (BindingFlags.InvokeMethod)) == 0) { for(int i = 0; i < parameterInfos.Length; i ++) { // a null argument type implies a null arg which is always a perfect match if (argumentTypes[i] != null && parameterInfos[i].ParameterType != argumentTypes[i]) return false; } } } #endregion } } #endregion return true; } #endregion #endregion #region Private Data Members private IntPtr m_cache; private RuntimeTypeHandle m_handle; private class TypeCacheQueue { // must be a power of 2 for this to work const int QUEUE_SIZE = 4; Object[] liveCache; internal TypeCacheQueue() { liveCache = new Object[QUEUE_SIZE]; } } private static TypeCacheQueue s_typeCache = null; #endregion #region Constructor private RuntimeType(RuntimeTypeHandle typeHandle) { m_handle = typeHandle; } internal RuntimeType() {} #endregion #region Private\Internal Members [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal override bool CacheEquals(object o) { RuntimeType m = o as RuntimeType; if (m == null) return false; return m.m_handle.Equals(m_handle); } private new RuntimeTypeCache Cache { get { if (m_cache.IsNull()) { IntPtr newgcHandle = m_handle.GetGCHandle(GCHandleType.WeakTrackResurrection); IntPtr gcHandle = Interlocked.CompareExchange(ref m_cache, newgcHandle, (IntPtr)0); if (!gcHandle.IsNull()) m_handle.FreeGCHandle(newgcHandle); } RuntimeTypeCache cache = GCHandle.InternalGet(m_cache) as RuntimeTypeCache; if (cache == null) { cache = new RuntimeTypeCache(this); RuntimeTypeCache existingCache = GCHandle.InternalCompareExchange(m_cache, cache, null, false) as RuntimeTypeCache; if (existingCache != null) cache = existingCache; if (s_typeCache == null) s_typeCache = new TypeCacheQueue(); //s_typeCache.Add(cache); } /* RuntimeTypeCache cache = m_cache as RuntimeTypeCache; if (cache == null) { cache = new RuntimeTypeCache(TypeHandle); RuntimeTypeCache existingCache = Interlocked.CompareExchange(ref m_cache, cache, null) as RuntimeTypeCache; if (existingCache != null) cache = existingCache; } */ ASSERT.CONSISTENCY_CHECK(cache != null); return cache; } } #endregion #region Type Overrides #region Get XXXInfo Candidates private MethodInfo[] GetMethodCandidates( String name, BindingFlags bindingAttr, CallingConventions callConv, Type[] types, bool allowPrefixLookup) { bool prefixLookup, ignoreCase; MemberListType listType; RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); List candidates = new List (); CerArrayList cache = Cache.GetMethodList(listType, name); bindingAttr ^= BindingFlags.DeclaredOnly; for (int i = 0; i < cache.Count; i++) { RuntimeMethodInfo methodInfo = cache[i]; if ((bindingAttr & methodInfo.BindingFlags) == methodInfo.BindingFlags && FilterApplyMethodBaseInfo(methodInfo, bindingAttr, callConv, types) && (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(methodInfo, name, ignoreCase))) { candidates.Add(methodInfo); } } return candidates.ToArray(); } private ConstructorInfo[] GetConstructorCandidates( string name, BindingFlags bindingAttr, CallingConventions callConv, Type[] types, bool allowPrefixLookup) { bool prefixLookup, ignoreCase; MemberListType listType; RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); List candidates = new List (); CerArrayList cache = Cache.GetConstructorList(listType, name); bindingAttr ^= BindingFlags.DeclaredOnly; for (int i = 0; i < cache.Count; i++) { RuntimeConstructorInfo constructorInfo = cache[i]; if ((bindingAttr & constructorInfo.BindingFlags) == constructorInfo.BindingFlags && FilterApplyMethodBaseInfo(constructorInfo, bindingAttr, callConv, types) && (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(constructorInfo, name, ignoreCase))) { candidates.Add(constructorInfo); } } return candidates.ToArray(); } private PropertyInfo[] GetPropertyCandidates( String name, BindingFlags bindingAttr, Type[] types, bool allowPrefixLookup) { bool prefixLookup, ignoreCase; MemberListType listType; RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); List candidates = new List (); CerArrayList cache = Cache.GetPropertyList(listType, name); bindingAttr ^= BindingFlags.DeclaredOnly; for (int i = 0; i < cache.Count; i++) { RuntimePropertyInfo propertyInfo = cache[i]; if ((bindingAttr & propertyInfo.BindingFlags) == propertyInfo.BindingFlags && (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(propertyInfo, name, ignoreCase)) && (types == null || (propertyInfo.GetIndexParameters().Length == types.Length))) { candidates.Add(propertyInfo); } } return candidates.ToArray(); } private EventInfo[] GetEventCandidates(String name, BindingFlags bindingAttr, bool allowPrefixLookup) { bool prefixLookup, ignoreCase; MemberListType listType; RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); List candidates = new List (); CerArrayList cache = Cache.GetEventList(listType, name); bindingAttr ^= BindingFlags.DeclaredOnly; for (int i = 0; i < cache.Count; i++) { RuntimeEventInfo eventInfo = cache[i]; if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags && (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(eventInfo, name, ignoreCase))) { candidates.Add(eventInfo); } } return candidates.ToArray(); } private FieldInfo[] GetFieldCandidates(String name, BindingFlags bindingAttr, bool allowPrefixLookup) { bool prefixLookup, ignoreCase; MemberListType listType; RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); List candidates = new List (); CerArrayList cache = Cache.GetFieldList(listType, name); bindingAttr ^= BindingFlags.DeclaredOnly; for (int i = 0; i < cache.Count; i++) { RuntimeFieldInfo fieldInfo = cache[i]; if ((bindingAttr & fieldInfo.BindingFlags) == fieldInfo.BindingFlags && (!prefixLookup || FilterApplyPrefixLookup(fieldInfo, name, ignoreCase))) { candidates.Add(fieldInfo); } } return candidates.ToArray(); } private Type[] GetNestedTypeCandidates(String fullname, BindingFlags bindingAttr, bool allowPrefixLookup) { bool prefixLookup, ignoreCase; bindingAttr &= ~BindingFlags.Static; string name, ns; MemberListType listType; SplitName(fullname, out name, out ns); RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType); List candidates = new List (); CerArrayList cache = Cache.GetNestedTypeList(listType, name); for (int i = 0; i < cache.Count; i++) { RuntimeType nestedClass = cache[i]; if (RuntimeType.FilterApplyType(nestedClass, bindingAttr, name, prefixLookup, ns)) { candidates.Add(nestedClass); } } return candidates.ToArray(); } #endregion #region Get All XXXInfos public override MethodInfo[] GetMethods(BindingFlags bindingAttr) { return GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, false); } [System.Runtime.InteropServices.ComVisible(true)] public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) { return GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false); } public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) { return GetPropertyCandidates(null, bindingAttr, null, false); } public override EventInfo[] GetEvents(BindingFlags bindingAttr) { return GetEventCandidates(null, bindingAttr, false); } public override FieldInfo[] GetFields(BindingFlags bindingAttr) { return GetFieldCandidates(null, bindingAttr, false); } public override Type[] GetInterfaces() { CerArrayList candidates = this.Cache.GetInterfaceList(MemberListType.All, null); Type[] interfaces = new Type[candidates.Count]; for (int i = 0; i < candidates.Count; i++) JitHelpers.UnsafeSetArrayElement(interfaces, i, candidates[i]); return interfaces; } public override Type[] GetNestedTypes(BindingFlags bindingAttr) { return GetNestedTypeCandidates(null, bindingAttr, false); } public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { MethodInfo[] methods = GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, false); ConstructorInfo[] constructors = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false); PropertyInfo[] properties = GetPropertyCandidates(null, bindingAttr, null, false); EventInfo[] events = GetEventCandidates(null, bindingAttr, false); FieldInfo[] fields = GetFieldCandidates(null, bindingAttr, false); Type[] nestedTypes = GetNestedTypeCandidates(null, bindingAttr, false); // Interfaces are excluded from the result of GetMembers MemberInfo[] members = new MemberInfo[ methods.Length + constructors.Length + properties.Length + events.Length + fields.Length + nestedTypes.Length]; int i = 0; Array.Copy(methods, 0, members, i, methods.Length); i += methods.Length; Array.Copy(constructors, 0, members, i, constructors.Length); i += constructors.Length; Array.Copy(properties, 0, members, i, properties.Length); i += properties.Length; Array.Copy(events, 0, members, i, events.Length); i += events.Length; Array.Copy(fields, 0, members, i, fields.Length); i += fields.Length; Array.Copy(nestedTypes, 0, members, i, nestedTypes.Length); i += nestedTypes.Length; ASSERT.POSTCONDITION(i == members.Length); return members; } public override InterfaceMapping GetInterfaceMap(Type ifaceType) { if (IsGenericParameter) throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter")); if (ifaceType == null) throw new ArgumentNullException("ifaceType"); if (!(ifaceType is RuntimeType)) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType"); RuntimeType ifaceRtType = ifaceType as RuntimeType; RuntimeTypeHandle ifaceRtTypeHandle = ifaceRtType.GetTypeHandleInternal(); int firstIfaceSlot = GetTypeHandleInternal().GetFirstSlotForInterface(ifaceRtType.GetTypeHandleInternal()); ASSERT.CONSISTENCY_CHECK(ifaceType.IsInterface); // GetFirstSlotForInterface enforces this invariant ASSERT.CONSISTENCY_CHECK(!IsInterface); // GetFirstSlotForInterface enforces this invariant int ifaceSlotCount = ifaceRtTypeHandle.GetInterfaceMethodSlots(); int ifaceStaticMethodCount = 0; // @Optimization - Most interface have the same number of static members. // Filter out static methods for (int i = 0; i < ifaceSlotCount; i ++) { if ((ifaceRtTypeHandle.GetMethodAt(i).GetAttributes() & MethodAttributes.Static) != 0) ifaceStaticMethodCount++; } int ifaceInstanceMethodCount = ifaceSlotCount - ifaceStaticMethodCount; InterfaceMapping im; im.InterfaceType = ifaceType; im.TargetType = this; im.InterfaceMethods = new MethodInfo[ifaceInstanceMethodCount]; im.TargetMethods = new MethodInfo[ifaceInstanceMethodCount]; for(int i = 0; i < ifaceSlotCount; i++) { RuntimeMethodHandle ifaceRtMethodHandle = ifaceRtTypeHandle.GetMethodAt(i); if ((ifaceRtTypeHandle.GetMethodAt(i).GetAttributes() & MethodAttributes.Static) != 0) continue; bool mayNeedInstantiatingStub = ifaceRtTypeHandle.HasInstantiation() && !ifaceRtTypeHandle.IsGenericTypeDefinition(); // if it is an instantiated type get the InstantiatedMethodDesc if needed if (mayNeedInstantiatingStub) ifaceRtMethodHandle = ifaceRtMethodHandle.GetInstantiatingStubIfNeeded(ifaceRtTypeHandle); MethodBase ifaceMethodBase = RuntimeType.GetMethodBase(ifaceRtTypeHandle, ifaceRtMethodHandle); ASSERT.CONSISTENCY_CHECK(ifaceMethodBase is RuntimeMethodInfo); im.InterfaceMethods[i] = (MethodInfo)ifaceMethodBase; // If the slot is -1, then virtual stub dispatch is active. // Should remove old "firstIfaceSlot + i" code when old behaviour disappears. int slot; if (firstIfaceSlot == -1) slot = GetTypeHandleInternal().GetInterfaceMethodImplementationSlot(ifaceRtTypeHandle, ifaceRtMethodHandle); else slot = firstIfaceSlot + i; if (slot == -1) continue; RuntimeTypeHandle classRtTypeHandle = GetTypeHandleInternal(); RuntimeMethodHandle classRtMethodHandle = classRtTypeHandle.GetMethodAt(slot); mayNeedInstantiatingStub = classRtTypeHandle.HasInstantiation() && !classRtTypeHandle.IsGenericTypeDefinition(); if (mayNeedInstantiatingStub) classRtMethodHandle = classRtMethodHandle.GetInstantiatingStubIfNeeded(classRtTypeHandle); MethodBase rtTypeMethodBase = RuntimeType.GetMethodBase(classRtTypeHandle, classRtMethodHandle); // a class may not implement all the methods of an interface (abstract class) so null is a valid value ASSERT.CONSISTENCY_CHECK(rtTypeMethodBase == null || rtTypeMethodBase is RuntimeMethodInfo); im.TargetMethods[i] = (MethodInfo)rtTypeMethodBase; } return im; } #endregion #region Find XXXInfo protected override MethodInfo GetMethodImpl( String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConv, Type[] types, ParameterModifier[] modifiers) { MethodInfo[] candidates = GetMethodCandidates(name, bindingAttr, callConv, types, false); if (candidates.Length == 0) return null; if (types == null || types.Length == 0) { if (candidates.Length == 1) { return candidates[0]; } else if (types == null) { for (int j = 1; j < candidates.Length; j++) { MethodInfo methodInfo = candidates[j]; if (!System.DefaultBinder.CompareMethodSigAndName(methodInfo, candidates[0])) { throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.Ambiguous")); } } // All the methods have the exact same name and sig so return the most derived one. return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates, candidates.Length) as MethodInfo; } } if (binder == null) binder = DefaultBinder; return binder.SelectMethod(bindingAttr, candidates, types, modifiers) as MethodInfo; } protected override ConstructorInfo GetConstructorImpl( BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { ConstructorInfo[] candidates = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, types, false); if (binder == null) binder = DefaultBinder; if (candidates.Length == 0) return null; if (types.Length == 0 && candidates.Length == 1) { ParameterInfo[] parameters = (candidates[0]).GetParametersNoCopy(); if (parameters == null || parameters.Length == 0) { return candidates[0]; } } if ((bindingAttr & BindingFlags.ExactBinding) != 0) return System.DefaultBinder.ExactBinding(candidates, types, modifiers) as ConstructorInfo; return binder.SelectMethod(bindingAttr, candidates, types, modifiers) as ConstructorInfo; } protected override PropertyInfo GetPropertyImpl( String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { if (name == null) throw new ArgumentNullException(); PropertyInfo[] candidates = GetPropertyCandidates(name, bindingAttr, types, false); if (binder == null) binder = DefaultBinder; if (candidates.Length == 0) return null; if (types == null || types.Length == 0) { // no arguments if (candidates.Length == 1) { if (returnType != null && returnType != candidates[0].PropertyType) return null; return candidates[0]; } else { if (returnType == null) // if we are here we have no args or property type to select over and we have more than one property with that name throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.Ambiguous")); } } if ((bindingAttr & BindingFlags.ExactBinding) != 0) return System.DefaultBinder.ExactPropertyBinding(candidates, returnType, types, modifiers); return binder.SelectProperty(bindingAttr, candidates, returnType, types, modifiers); } public override EventInfo GetEvent(String name, BindingFlags bindingAttr) { if (name == null) throw new ArgumentNullException(); bool ignoreCase; MemberListType listType; RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType); CerArrayList cache = Cache.GetEventList(listType, name); EventInfo match = null; bindingAttr ^= BindingFlags.DeclaredOnly; for (int i = 0; i < cache.Count; i++) { RuntimeEventInfo eventInfo = cache[i]; if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags) { if (match != null) throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.Ambiguous")); match = eventInfo; } } return match; } public override FieldInfo GetField(String name, BindingFlags bindingAttr) { if (name == null) throw new ArgumentNullException(); bool ignoreCase; MemberListType listType; RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType); CerArrayList cache = Cache.GetFieldList(listType, name); FieldInfo match = null; bindingAttr ^= BindingFlags.DeclaredOnly; bool multipleStaticFieldMatches = false; for (int i = 0; i < cache.Count; i++) { RuntimeFieldInfo fieldInfo = cache[i]; if ((bindingAttr & fieldInfo.BindingFlags) == fieldInfo.BindingFlags) { if (match != null) { if (fieldInfo.DeclaringType == match.DeclaringType) throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.Ambiguous")); if ((match.DeclaringType.IsInterface == true) && (fieldInfo.DeclaringType.IsInterface == true)) multipleStaticFieldMatches = true; } if (match == null || fieldInfo.DeclaringType.IsSubclassOf(match.DeclaringType) || match.DeclaringType.IsInterface) match = fieldInfo; } } if (multipleStaticFieldMatches && match.DeclaringType.IsInterface) throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.Ambiguous")); return match; } public override Type GetInterface(String fullname, bool ignoreCase) { if (fullname == null) throw new ArgumentNullException(); BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.NonPublic; bindingAttr &= ~BindingFlags.Static; if (ignoreCase) bindingAttr |= BindingFlags.IgnoreCase; string name, ns; MemberListType listType; SplitName(fullname, out name, out ns); RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType); CerArrayList cache = Cache.GetInterfaceList(listType, name); RuntimeType match = null; for (int i = 0; i < cache.Count; i++) { RuntimeType iface = cache[i]; if (RuntimeType.FilterApplyType(iface, bindingAttr, name, false, ns)) { if (match != null) throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.Ambiguous")); match = iface; } } return match; } public override Type GetNestedType(String fullname, BindingFlags bindingAttr) { if (fullname == null) throw new ArgumentNullException(); bool ignoreCase; bindingAttr &= ~BindingFlags.Static; string name, ns; MemberListType listType; SplitName(fullname, out name, out ns); RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType); CerArrayList cache = Cache.GetNestedTypeList(listType, name); RuntimeType match = null; for (int i = 0; i < cache.Count; i++) { RuntimeType nestedType = cache[i]; if (RuntimeType.FilterApplyType(nestedType, bindingAttr, name, false, ns)) { if (match != null) throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.Ambiguous")); match = nestedType; } } return match; } public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr) { if (name == null) throw new ArgumentNullException(); MethodInfo[] methods = new MethodInfo[0]; ConstructorInfo[] constructors = new ConstructorInfo[0]; PropertyInfo[] properties = new PropertyInfo[0]; EventInfo[] events = new EventInfo[0]; FieldInfo[] fields = new FieldInfo[0]; Type[] nestedTypes = new Type[0]; // Methods if ((type & MemberTypes.Method) != 0) methods = GetMethodCandidates(name, bindingAttr, CallingConventions.Any, null, true); // Constructors if ((type & MemberTypes.Constructor) != 0) constructors = GetConstructorCandidates(name, bindingAttr, CallingConventions.Any, null, true); // Properties if ((type & MemberTypes.Property) != 0) properties = GetPropertyCandidates(name, bindingAttr, null, true); // Events if ((type & MemberTypes.Event) != 0) events = GetEventCandidates(name, bindingAttr, true); // Fields if ((type & MemberTypes.Field) != 0) fields = GetFieldCandidates(name, bindingAttr, true); // NestedTypes if ((type & (MemberTypes.NestedType | MemberTypes.TypeInfo)) != 0) nestedTypes = GetNestedTypeCandidates(name, bindingAttr, true); switch(type) { case MemberTypes.Method | MemberTypes.Constructor: MethodBase[] compressBaseses = new MethodBase[methods.Length + constructors.Length]; Array.Copy(methods, compressBaseses, methods.Length); Array.Copy(constructors, 0, compressBaseses, methods.Length, constructors.Length); return compressBaseses; case MemberTypes.Method: return methods; case MemberTypes.Constructor: return constructors; case MemberTypes.Field: return fields; case MemberTypes.Property: return properties; case MemberTypes.Event: return events; case MemberTypes.NestedType: return nestedTypes; case MemberTypes.TypeInfo: return nestedTypes; } MemberInfo[] compressMembers = new MemberInfo[ methods.Length + constructors.Length + properties.Length + events.Length + fields.Length + nestedTypes.Length]; int i = 0; if (methods.Length > 0) Array.Copy(methods, 0, compressMembers, i, methods.Length); i += methods.Length; if (constructors.Length > 0) Array.Copy(constructors, 0, compressMembers, i, constructors.Length); i += constructors.Length; if (properties.Length > 0) Array.Copy(properties, 0, compressMembers, i, properties.Length); i += properties.Length; if (events.Length > 0) Array.Copy(events, 0, compressMembers, i, events.Length); i += events.Length; if (fields.Length > 0) Array.Copy(fields, 0, compressMembers, i, fields.Length); i += fields.Length; if (nestedTypes.Length > 0) Array.Copy(nestedTypes, 0, compressMembers, i, nestedTypes.Length); i += nestedTypes.Length; ASSERT.POSTCONDITION(i == compressMembers.Length); return compressMembers; } #endregion #region Identity public override Module Module { get { return GetTypeHandleInternal().GetModuleHandle().GetModule(); } } public override Assembly Assembly { get { return GetTypeHandleInternal().GetAssemblyHandle().GetAssembly(); } } public override RuntimeTypeHandle TypeHandle { get { return m_handle; } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal override RuntimeTypeHandle GetTypeHandleInternal() { return m_handle; } internal override TypeCode GetTypeCodeInternal() { TypeCode typeCode = Cache.TypeCode; if (typeCode != TypeCode.Empty) return typeCode; CorElementType corElementType = GetTypeHandleInternal().GetCorElementType(); switch (corElementType) { case CorElementType.Boolean: typeCode = TypeCode.Boolean; break; case CorElementType.Char: typeCode = TypeCode.Char; break; case CorElementType.I1: typeCode = TypeCode.SByte; break; case CorElementType.U1: typeCode = TypeCode.Byte; break; case CorElementType.I2: typeCode = TypeCode.Int16; break; case CorElementType.U2: typeCode = TypeCode.UInt16; break; case CorElementType.I4: typeCode = TypeCode.Int32; break; case CorElementType.U4: typeCode = TypeCode.UInt32; break; case CorElementType.I8: typeCode = TypeCode.Int64; break; case CorElementType.U8: typeCode = TypeCode.UInt64; break; case CorElementType.R4: typeCode = TypeCode.Single; break; case CorElementType.R8: typeCode = TypeCode.Double; break; case CorElementType.String: typeCode = TypeCode.String; break; case CorElementType.ValueType: if (this == Convert.ConvertTypes[(int)TypeCode.Decimal]) typeCode = TypeCode.Decimal; else if (this == Convert.ConvertTypes[(int)TypeCode.DateTime]) typeCode = TypeCode.DateTime; else if (this.IsEnum) typeCode = Type.GetTypeCode(Enum.GetUnderlyingType(this)); else typeCode = TypeCode.Object; break; default: if (this == Convert.ConvertTypes[(int)TypeCode.DBNull]) typeCode = TypeCode.DBNull; else if (this == Convert.ConvertTypes[(int)TypeCode.String]) typeCode = TypeCode.String; else typeCode = TypeCode.Object; break; } Cache.TypeCode = typeCode; return typeCode; } public override MethodBase DeclaringMethod { get { if (!IsGenericParameter) throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter")); RuntimeMethodHandle declaringMethod = GetTypeHandleInternal().GetDeclaringMethod(); if (declaringMethod.IsNullHandle()) return null; return GetMethodBase(declaringMethod.GetDeclaringType(), declaringMethod); } } #endregion #region Hierarchy public override bool IsInstanceOfType(Object o) { return GetTypeHandleInternal().IsInstanceOfType(o); } [System.Runtime.InteropServices.ComVisible(true)] public override bool IsSubclassOf(Type type) { if (type == null) throw new ArgumentNullException("type"); ASSERT.PRECONDITION(type is RuntimeType); Type baseType = BaseType; while (baseType != null) { if (baseType == type) return true; baseType = baseType.BaseType; } // pretty much everything is a subclass of object, even interfaces // notice that interfaces are really odd because they do not have a BaseType // yet IsSubclassOf(typeof(object)) returns true if (type == typeof(Object) && type != this) return true; return false; } public override Type BaseType { get { if (IsInterface) return null; if (m_handle.IsGenericVariable()) { Type[] constraints = GetGenericParameterConstraints(); Type baseType = typeof(object); for (int i = 0; i < constraints.Length; i++) { Type constraint = constraints[i]; if (constraint.IsInterface) continue; if (constraint.IsGenericParameter) { GenericParameterAttributes special; special = constraint.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask; if ((special & GenericParameterAttributes.ReferenceTypeConstraint) == 0 && (special & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0) continue; } baseType = constraint; } if (baseType == typeof(object)) { GenericParameterAttributes special; special = GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask; if ((special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) baseType = typeof(ValueType); } return baseType; } return m_handle.GetBaseTypeHandle().GetRuntimeType(); } } public override Type UnderlyingSystemType { get { // Origional Comment: Return the underlying Type that represents the IReflect Object. // For expando object, this is the (Object) IReflectInstance.GetType(). For Type object it is this. return this; } } #endregion #region Name public override String FullName { get { return Cache.GetFullName(); } } public override String AssemblyQualifiedName { get { if (!IsGenericTypeDefinition && ContainsGenericParameters) return null; return Assembly.CreateQualifiedName(this.Assembly.FullName, this.FullName); } } public override String Namespace { get { string ns = Cache.GetNameSpace(); if (ns == null || ns.Length == 0) return null; return ns; } } #endregion #region Attributes protected override TypeAttributes GetAttributeFlagsImpl() { return m_handle.GetAttributes(); } public override Guid GUID { get { Guid result = new Guid (); GetGUID(ref result); return result; } } [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void GetGUID(ref Guid result); protected override bool IsContextfulImpl() { return GetTypeHandleInternal().IsContextful(); } /* protected override bool IsMarshalByRefImpl() { return GetTypeHandleInternal().IsMarshalByRef(); } */ protected override bool IsByRefImpl() { CorElementType corElemType = GetTypeHandleInternal().GetCorElementType(); return (corElemType == CorElementType.ByRef); } protected override bool IsPrimitiveImpl() { CorElementType corElemType = GetTypeHandleInternal().GetCorElementType(); return (corElemType >= CorElementType.Boolean && corElemType <= CorElementType.R8) || corElemType == CorElementType.I || corElemType == CorElementType.U; } protected override bool IsPointerImpl() { CorElementType corElemType = GetTypeHandleInternal().GetCorElementType(); return (corElemType == CorElementType.Ptr); } protected override bool IsCOMObjectImpl() { return GetTypeHandleInternal().IsComObject(false); } internal override bool HasProxyAttributeImpl() { return GetTypeHandleInternal().HasProxyAttribute(); } protected override bool HasElementTypeImpl() { return (IsArray || IsPointer || IsByRef); } public override GenericParameterAttributes GenericParameterAttributes { get { if (!IsGenericParameter) throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter")); GenericParameterAttributes attributes; GetTypeHandleInternal().GetModuleHandle().GetMetadataImport().GetGenericParamProps(MetadataToken, out attributes); return attributes; } } #endregion #region Arrays internal override bool IsSzArray { get { CorElementType corElemType = GetTypeHandleInternal().GetCorElementType(); return (corElemType == CorElementType.SzArray); } } protected override bool IsArrayImpl() { CorElementType corElemType = GetTypeHandleInternal().GetCorElementType(); return (corElemType == CorElementType.Array || corElemType == CorElementType.SzArray); } public override int GetArrayRank() { if (!IsArrayImpl()) throw new ArgumentException(Environment.GetResourceString("Argument_HasToBeArrayClass")); return GetTypeHandleInternal().GetArrayRank(); } public override Type GetElementType() { return GetTypeHandleInternal().GetElementType().GetRuntimeType(); } #endregion #region Generics public override Type[] GetGenericArguments() { Type[] rtypes = null; RuntimeTypeHandle[] types = GetRootElementType().GetTypeHandleInternal().GetInstantiation(); if (types != null) { rtypes = new Type[types.Length]; for (int i = 0; i < types.Length; i++) rtypes[i] = types[i].GetRuntimeType(); } else { rtypes = new Type[0]; } return rtypes; } public override Type MakeGenericType(Type[] instantiation) { if (instantiation == null) throw new ArgumentNullException("instantiation"); Type[] instantiationCopy = new Type[instantiation.Length]; for (int i = 0; i < instantiation.Length; i ++) instantiationCopy[i] = instantiation[i]; instantiation = instantiationCopy; if (!IsGenericTypeDefinition) throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Arg_NotGenericTypeDefinition"), this)); for (int i = 0; i < instantiation.Length; i ++) { if (instantiation[i] == null) throw new ArgumentNullException(); if (!(instantiation[i] is RuntimeType)) return new TypeBuilderInstantiation(this, instantiation); } Type[] genericParameters = GetGenericArguments(); SanityCheckGenericArguments(instantiation, genericParameters); RuntimeTypeHandle[] typeHandles = new RuntimeTypeHandle[instantiation.Length]; for (int i = 0; i < instantiation.Length; i++) typeHandles[i] = instantiation[i].GetTypeHandleInternal(); Type ret = null; try { ret = m_handle.Instantiate(typeHandles).GetRuntimeType(); } catch (TypeLoadException e) { ValidateGenericArguments(this, instantiation, e); throw e; } return ret; } public override bool IsGenericTypeDefinition { get { return m_handle.IsGenericTypeDefinition(); } } public override bool IsGenericParameter { get { return m_handle.IsGenericVariable(); } } public override int GenericParameterPosition { get { if (!IsGenericParameter) throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter")); return m_handle.GetGenericVariableIndex(); } } public override Type GetGenericTypeDefinition() { if (!IsGenericType) throw new InvalidOperationException(); return m_handle.GetGenericTypeDefinition().GetRuntimeType(); } public override bool IsGenericType { get { return HasElementType ? false : GetTypeHandleInternal().HasInstantiation(); } } public override bool ContainsGenericParameters { get { return GetRootElementType().GetTypeHandleInternal().ContainsGenericVariables(); } } public override Type[] GetGenericParameterConstraints() { if (!IsGenericParameter) throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter")); RuntimeTypeHandle[] constraintHandles = m_handle.GetConstraints(); Type[] constraints = new Type[constraintHandles.Length]; for (int i = 0; i < constraints.Length; i++) constraints[i] = constraintHandles[i].GetRuntimeType(); return constraints; } #endregion #region Misc public override Type MakePointerType() { return m_handle.MakePointer().GetRuntimeType(); } public override Type MakeByRefType() { return m_handle.MakeByRef().GetRuntimeType(); } public override Type MakeArrayType() { return m_handle.MakeSZArray().GetRuntimeType(); } public override Type MakeArrayType(int rank) { if (rank <= 0) throw new IndexOutOfRangeException(); return m_handle.MakeArray(rank).GetRuntimeType(); } public override StructLayoutAttribute StructLayoutAttribute { get { return (StructLayoutAttribute)StructLayoutAttribute.GetCustomAttribute(this); } } #endregion #region Invoke Member private const BindingFlags MemberBindingMask = (BindingFlags)0x000000FF; private const BindingFlags InvocationMask = (BindingFlags)0x0000FF00; private const BindingFlags BinderNonCreateInstance = BindingFlags.InvokeMethod | BinderGetSetField | BinderGetSetProperty; private const BindingFlags BinderGetSetProperty = BindingFlags.GetProperty | BindingFlags.SetProperty; private const BindingFlags BinderSetInvokeProperty = BindingFlags.InvokeMethod | BindingFlags.SetProperty; private const BindingFlags BinderGetSetField = BindingFlags.GetField | BindingFlags.SetField; private const BindingFlags BinderSetInvokeField = BindingFlags.SetField | BindingFlags.InvokeMethod; private const BindingFlags BinderNonFieldGetSet = (BindingFlags)0x00FFF300; private const BindingFlags ClassicBindingMask = BindingFlags.InvokeMethod | BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty; private static Type s_typedRef = typeof(TypedReference); [MethodImplAttribute(MethodImplOptions.InternalCall)] static private extern bool CanValueSpecialCast(IntPtr valueType, IntPtr targetType); [MethodImplAttribute(MethodImplOptions.InternalCall)] static private extern Object AllocateObjectForByRef(RuntimeTypeHandle type, object value); internal unsafe Object CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr) { // this method is used by invocation in reflection to if (IsInstanceOfType(value)) return value; // if this is a ByRef get the element type and bool isByRef = IsByRef; if (isByRef) { Type elementType = GetElementType(); if (elementType.IsInstanceOfType(value) || value == null) { // need to create an instance of the ByRef if null was provided, but only if primitive, enum or value type return AllocateObjectForByRef(elementType.TypeHandle, value); } } else if (value == null) return value; else if (this == s_typedRef) // everything works for a typedref return value; // bool needsSpecialCast = IsPointer || IsEnum || IsPrimitive; if (needsSpecialCast) { Type valueType; Pointer pointer = value as Pointer; if (pointer != null) valueType = pointer.GetPointerType(); else valueType = value.GetType(); if (CanValueSpecialCast(valueType.TypeHandle.Value, TypeHandle.Value)) { if (pointer != null) return pointer.GetPointerValue(); else return value; } } if ((invokeAttr & BindingFlags.ExactBinding) == BindingFlags.ExactBinding) throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this)); if (binder != null && binder != Type.DefaultBinder) { value = binder.ChangeType(value, this, culture); if (IsInstanceOfType(value)) return value; // if this is a ByRef get the element type and if (isByRef) { Type elementType = GetElementType(); if (elementType.IsInstanceOfType(value) || value == null) return AllocateObjectForByRef(elementType.TypeHandle, value); } else if (value == null) return value; if (needsSpecialCast) { Type valueType; Pointer pointer = value as Pointer; if (pointer != null) valueType = pointer.GetPointerType(); else valueType = value.GetType(); if (CanValueSpecialCast(valueType.TypeHandle.Value, TypeHandle.Value)) { if (pointer != null) return pointer.GetPointerValue(); else return value; } } } throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this)); } [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] public override Object InvokeMember( String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) { if (IsGenericParameter) throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter")); #region Preconditions if ((bindingFlags & InvocationMask) == 0) // "Must specify binding flags describing the invoke operation required." throw new ArgumentException(Environment.GetResourceString("Arg_NoAccessSpec"),"bindingFlags"); // Provide a default binding mask if none is provided if ((bindingFlags & MemberBindingMask) == 0) { bindingFlags |= BindingFlags.Instance | BindingFlags.Public; if ((bindingFlags & BindingFlags.CreateInstance) == 0) bindingFlags |= BindingFlags.Static; } // There must not be more named parameters than provided arguments if (namedParams != null) { if (providedArgs != null) { if (namedParams.Length > providedArgs.Length) // "Named parameter array can not be bigger than argument array." throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"), "namedParams"); } else { if (namedParams.Length != 0) // "Named parameter array can not be bigger than argument array." throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"), "namedParams"); } } #endregion #region COM Interop #if FEATURE_COMINTEROP if (target != null && target.GetType().IsCOMObject) { #region Preconditions if ((bindingFlags & ClassicBindingMask) == 0) throw new ArgumentException(Environment.GetResourceString("Arg_COMAccess"), "bindingFlags"); if ((bindingFlags & BindingFlags.GetProperty) != 0 && (bindingFlags & ClassicBindingMask & ~(BindingFlags.GetProperty | BindingFlags.InvokeMethod)) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), "bindingFlags"); if ((bindingFlags & BindingFlags.InvokeMethod) != 0 && (bindingFlags & ClassicBindingMask & ~(BindingFlags.GetProperty | BindingFlags.InvokeMethod)) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), "bindingFlags"); if ((bindingFlags & BindingFlags.SetProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.SetProperty) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags"); if ((bindingFlags & BindingFlags.PutDispProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.PutDispProperty) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags"); if ((bindingFlags & BindingFlags.PutRefDispProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.PutRefDispProperty) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags"); #endregion if(!RemotingServices.IsTransparentProxy(target)) { #region Non-TransparentProxy case if (name == null) throw new ArgumentNullException("name"); if (culture == null) culture = Thread.CurrentThread.CurrentCulture; bool[] isByRef = modifiers == null ? null : modifiers[0].IsByRefArray; return InvokeDispMethod(name, bindingFlags, target, providedArgs, isByRef, culture.LCID, namedParams); #endregion } else { #region TransparentProxy case return ((MarshalByRefObject)target).InvokeMember(name, bindingFlags, binder, providedArgs, modifiers, culture, namedParams); #endregion } } #endif // FEATURE_COMINTEROP #endregion #region Check that any named paramters are not null if (namedParams != null && Array.IndexOf(namedParams, null) != -1) // "Named parameter value must not be null." throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamNull"),"namedParams"); #endregion int argCnt = (providedArgs != null) ? providedArgs.Length : 0; #region Get a Binder if (binder == null) binder = DefaultBinder; bool bDefaultBinder = (binder == DefaultBinder); #endregion #region Delegate to Activator.CreateInstance if ((bindingFlags & BindingFlags.CreateInstance) != 0) { if ((bindingFlags & BindingFlags.CreateInstance) != 0 && (bindingFlags & BinderNonCreateInstance) != 0) // "Can not specify both CreateInstance and another access type." throw new ArgumentException(Environment.GetResourceString("Arg_CreatInstAccess"),"bindingFlags"); return Activator.CreateInstance(this, bindingFlags, binder, providedArgs, culture); } #endregion // PutDispProperty and\or PutRefDispProperty ==> SetProperty. if ((bindingFlags & (BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty)) != 0) bindingFlags |= BindingFlags.SetProperty; #region Name if (name == null) throw new ArgumentNullException("name"); if (name.Length == 0 || name.Equals(@"[DISPID=0]")) { name = GetDefaultMemberName(); if (name == null) { // in InvokeMember we always pretend there is a default member if none is provided and we make it ToString name = "ToString"; } } #endregion #region GetField or SetField bool IsGetField = (bindingFlags & BindingFlags.GetField) != 0; bool IsSetField = (bindingFlags & BindingFlags.SetField) != 0; if (IsGetField || IsSetField) { #region Preconditions if (IsGetField) { if (IsSetField) // "Can not specify both Get and Set on a field." throw new ArgumentException(Environment.GetResourceString("Arg_FldSetGet"),"bindingFlags"); if ((bindingFlags & BindingFlags.SetProperty) != 0) // "Can not specify both GetField and SetProperty." throw new ArgumentException(Environment.GetResourceString("Arg_FldGetPropSet"),"bindingFlags"); } else { ASSERT.CONSISTENCY_CHECK(IsSetField); if (providedArgs == null) throw new ArgumentNullException("providedArgs"); if ((bindingFlags & BindingFlags.GetProperty) != 0) // "Can not specify both SetField and GetProperty." throw new ArgumentException(Environment.GetResourceString("Arg_FldSetPropGet"),"bindingFlags"); if ((bindingFlags & BindingFlags.InvokeMethod) != 0) // "Can not specify Set on a Field and Invoke on a method." throw new ArgumentException(Environment.GetResourceString("Arg_FldSetInvoke"),"bindingFlags"); } #endregion #region Lookup Field FieldInfo selFld = null; FieldInfo[] flds = GetMember(name, MemberTypes.Field, bindingFlags) as FieldInfo[]; ASSERT.CONSISTENCY_CHECK(flds != null); if (flds.Length == 1) { selFld = flds[0]; } else if (flds.Length > 0) { selFld = binder.BindToField(bindingFlags, flds, IsGetField ? Empty.Value : providedArgs[0], culture); } #endregion if (selFld != null) { #region Invocation on a field if (selFld.FieldType.IsArray || selFld.FieldType == typeof(System.Array)) { #region Invocation of an array Field int idxCnt; if ((bindingFlags & BindingFlags.GetField) != 0) { idxCnt = argCnt; } else { idxCnt = argCnt - 1; } if (idxCnt > 0) { // Verify that all of the index values are ints int[] idx = new int[idxCnt]; for (int i=0;i 1); finalists = new MethodInfo[results.Count]; results.CopyTo(finalists); } #endregion } #endregion ASSERT.CONSISTENCY_CHECK(LOGIC.IMPLIES(finalists != null, finalist != null)); #region BindingFlags.GetProperty or BindingFlags.SetProperty if (finalist == null && isGetProperty || isSetProperty) { #region Lookup Property PropertyInfo[] semiFinalists = GetMember(name, MemberTypes.Property, bindingFlags) as PropertyInfo[]; ArrayList results = null; for(int i = 0; i < semiFinalists.Length; i ++) { MethodInfo semiFinalist = null; if (isSetProperty) { semiFinalist = semiFinalists[i].GetSetMethod(true); } else { semiFinalist = semiFinalists[i].GetGetMethod(true); } if (semiFinalist == null) continue; if (!FilterApplyMethodBaseInfo(semiFinalist, bindingFlags, null, CallingConventions.Any, new Type[argCnt], false)) continue; if (finalist == null) { finalist = semiFinalist; } else { if (results == null) { results = new ArrayList(semiFinalists.Length); results.Add(finalist); } results.Add(semiFinalist); } } if (results != null) { ASSERT.CONSISTENCY_CHECK(results.Count > 1); finalists = new MethodInfo[results.Count]; results.CopyTo(finalists); } #endregion } #endregion if (finalist != null) { #region Invoke if (finalists == null && argCnt == 0 && finalist.GetParametersNoCopy().Length == 0 && (bindingFlags & BindingFlags.OptionalParamBinding) == 0) { //if (useCache && argCnt == props[0].GetParameters().Length) // AddMethodToCache(name, bindingFlags, argCnt, providedArgs, props[0]); return finalist.Invoke(target, bindingFlags, binder, providedArgs, culture); } if (finalists == null) finalists = new MethodInfo[] { finalist }; if (providedArgs == null) providedArgs = new Object[0]; Object state = null; MethodBase invokeMethod = null; try { invokeMethod = binder.BindToMethod(bindingFlags, finalists, ref providedArgs, modifiers, culture, namedParams, out state); } catch(MissingMethodException) { } if (invokeMethod == null) throw new MissingMethodException(FullName, name); //if (useCache && argCnt == invokeMethod.GetParameters().Length) // AddMethodToCache(name, bindingFlags, argCnt, providedArgs, invokeMethod); Object result = ((MethodInfo)invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture); if (state != null) binder.ReorderArgumentArray(ref providedArgs, state); return result; #endregion } throw new MissingMethodException(FullName, name); } #endregion #endregion #region Object Overrides public override bool Equals(object obj) { // ComObjects are identified by the instance of the Type object and not the TypeHandle. return obj == this; } public override int GetHashCode() { #if WIN32 return (int)GetTypeHandleInternal().Value; #else long l = (long)GetTypeHandleInternal().Value; return unchecked((int)l); #endif } public override String ToString() { return Cache.GetToString(); } #endregion #region ICloneable public Object Clone() { return this; } #endregion #region ISerializable public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) throw new ArgumentNullException("info"); UnitySerializationHolder.GetUnitySerializationInfo(info, this); } #endregion #region ICustomAttributeProvider public override Object[] GetCustomAttributes(bool inherit) { return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType, inherit); } public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) throw new ArgumentNullException("attributeType"); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType, inherit); } public override bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) throw new ArgumentNullException("attributeType"); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); return CustomAttribute.IsDefined(this, attributeRuntimeType, inherit); } #endregion #region MemberInfo Overrides public override String Name { get { return Cache.GetName(); } } public override MemberTypes MemberType { get { if (this.IsPublic || this.IsNotPublic) return MemberTypes.TypeInfo; else return MemberTypes.NestedType; } } public override Type DeclaringType { get { return Cache.GetEnclosingType(); } } public override Type ReflectedType { get { return DeclaringType; } } public override int MetadataToken { get { return m_handle.GetToken(); } } #endregion #region Legacy Internal internal void CreateInstanceCheckThis() { if (this is ReflectionOnlyType) throw new ArgumentException(Environment.GetResourceString("Arg_ReflectionOnlyInvoke")); if (ContainsGenericParameters) throw new ArgumentException( String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Acc_CreateGenericEx"), this)); Type elementType = this.GetRootElementType(); if (elementType == typeof(ArgIterator)) throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Acc_CreateArgIterator"))); if (elementType == typeof(void)) throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Acc_CreateVoid"))); } internal Object CreateInstanceImpl( BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) { CreateInstanceCheckThis(); Object server = null; try { try { // Store the activation attributes in thread local storage. // These attributes are later picked up by specialized // activation services like remote activation services to // influence the activation. if(null != activationAttributes) { ActivationServices.PushActivationAttributes(this, activationAttributes); } if (args == null) args = new Object[0]; int argCnt = args.Length; // Without a binder we need to do use the default binder... if (binder == null) binder = DefaultBinder; // deal with the __COMObject case first. It is very special because from a reflection point of view it has no ctors // so a call to GetMemberCons would fail if (argCnt == 0 && (bindingAttr & BindingFlags.Public) != 0 && (bindingAttr & BindingFlags.Instance) != 0 && (IsGenericCOMObjectImpl() || IsSubclassOf(typeof(ValueType)))) { server = CreateInstanceImpl(((bindingAttr & BindingFlags.NonPublic) != 0) ? false : true); } else { MethodBase[] candidates = GetConstructors(bindingAttr); ArrayList matches = new ArrayList(candidates.Length); Type[] argsType = new Type[argCnt]; for(int i = 0; i < argCnt; i ++) { if (args[i] != null) { argsType[i] = args[i].GetType(); } } for(int i = 0; i < candidates.Length; i ++) { MethodBase canidate = candidates[i]; if (FilterApplyMethodBaseInfo( candidates[i], bindingAttr, null, CallingConventions.Any, argsType, false)) matches.Add(candidates[i]); } MethodBase[] cons = new MethodBase[matches.Count]; matches.CopyTo(cons); if (cons != null && cons.Length == 0) cons = null; if (cons == null) { // Null out activation attributes before throwing exception if(null != activationAttributes) { ActivationServices.PopActivationAttributes(this); activationAttributes = null; } throw new MissingMethodException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("MissingConstructor_Name"), FullName)); } // It would be strange to have an argCnt of 0 and more than // one constructor. if (argCnt == 0 && cons.Length == 1 && (bindingAttr & BindingFlags.OptionalParamBinding) == 0) server = Activator.CreateInstance(this, true); else { // MethodBase invokeMethod = binder.BindToMethod(cons,args,null,null,culture); MethodBase invokeMethod; Object state = null; try { invokeMethod = binder.BindToMethod(bindingAttr,cons,ref args,null,culture,null, out state); } catch (MissingMethodException) { invokeMethod = null; } if (invokeMethod == null) { // Null out activation attributes before throwing exception if(null != activationAttributes) { ActivationServices.PopActivationAttributes(this); activationAttributes = null; } throw new MissingMethodException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("MissingConstructor_Name"), FullName)); } // If we're creating a delegate, we're about to call a // constructor taking an integer to represent a target // method. Since this is very difficult (and expensive) // to verify, we're just going to demand UnmanagedCode // permission before allowing this. Partially trusted // clients can instead use Delegate.CreateDelegate, // which allows specification of the target method via // name or MethodInfo. //if (isDelegate) if (typeof(Delegate).IsAssignableFrom(invokeMethod.DeclaringType)) new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); server = ((ConstructorInfo) invokeMethod).Invoke(bindingAttr,binder,args,culture); if (state != null) binder.ReorderArgumentArray(ref args, state); } } } finally { // Reset the TLS to null if(null != activationAttributes) { ActivationServices.PopActivationAttributes(this); activationAttributes = null; } } } catch (Exception) { throw; } //Console.WriteLine(server); return server; } // the cache entry class ActivatorCacheEntry { // the type to cache internal Type m_type; // the delegate containing the call to the ctor, will be replaced by an IntPtr to feed a calli with internal CtorDelegate m_ctor; internal RuntimeMethodHandle m_hCtorMethodHandle; // Is a security internal bool m_bNeedSecurityCheck; // Lazy initialization was performed internal bool m_bFullyInitialized; internal ActivatorCacheEntry(Type t, RuntimeMethodHandle rmh, bool bNeedSecurityCheck) { m_type = t; m_bNeedSecurityCheck = bNeedSecurityCheck; m_hCtorMethodHandle = rmh; } } //ActivatorCache class ActivatorCache { const int CACHE_SIZE = 16; int hash_counter; //Counter for wrap around ActivatorCacheEntry[] cache = new ActivatorCacheEntry[CACHE_SIZE]; ConstructorInfo delegateCtorInfo; PermissionSet delegateCreatePermissions; private void InitializeDelegateCreator() { // No synchronization needed here. In the worst case we create extra garbage PermissionSet ps = new PermissionSet(PermissionState.None); ps.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)); ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)); System.Threading.Thread.MemoryBarrier(); delegateCreatePermissions = ps; ConstructorInfo ctorInfo = typeof(CtorDelegate).GetConstructor(new Type[] {typeof(Object), typeof(IntPtr)}); System.Threading.Thread.MemoryBarrier(); delegateCtorInfo = ctorInfo; // this assignment should be last } private void InitializeCacheEntry(ActivatorCacheEntry ace) { if (!ace.m_type.IsValueType) { BCLDebug.Assert(!ace.m_hCtorMethodHandle.Equals(RuntimeMethodHandle.EmptyHandle), "Expected the default ctor method handle for a reference type."); if (delegateCtorInfo == null) InitializeDelegateCreator(); delegateCreatePermissions.Assert(); // No synchronization needed here. In the worst case we create extra garbage CtorDelegate ctor = (CtorDelegate)delegateCtorInfo.Invoke(new Object[] {null, ace.m_hCtorMethodHandle.GetFunctionPointer()}); System.Threading.Thread.MemoryBarrier(); ace.m_ctor = ctor; } ace.m_bFullyInitialized = true; } internal ActivatorCacheEntry GetEntry(Type t) { int index = hash_counter; for(int i = 0; i < CACHE_SIZE; i++) { ActivatorCacheEntry ace = cache[index]; if (ace != null && (Object)ace.m_type == (Object)t) // { if (!ace.m_bFullyInitialized) InitializeCacheEntry(ace); return ace; } index = (index+1)&(ActivatorCache.CACHE_SIZE-1); } return null; } internal void SetEntry(ActivatorCacheEntry ace) { // fill the the array backwards to hit the most recently filled entries first in GetEntry int index = (hash_counter-1)&(ActivatorCache.CACHE_SIZE-1); hash_counter = index; cache[index] = ace; } } static ActivatorCache s_ActivatorCache; // the slow path of CreateInstanceImpl private Object CreateInstanceSlow(bool publicOnly, bool fillCache) { RuntimeMethodHandle runtime_ctor = RuntimeMethodHandle.EmptyHandle; bool bNeedSecurityCheck = true; bool bCanBeCached = false; bool bSecurityCheckOff = false; CreateInstanceCheckThis(); if (!fillCache) bSecurityCheckOff = true; Object instance = RuntimeTypeHandle.CreateInstance(this, publicOnly, bSecurityCheckOff, ref bCanBeCached, ref runtime_ctor, ref bNeedSecurityCheck); if (bCanBeCached && fillCache) { ActivatorCache activatorCache = s_ActivatorCache; if(activatorCache == null) { // No synchronization needed here. In the worst case we create extra garbage activatorCache = new ActivatorCache(); System.Threading.Thread.MemoryBarrier(); s_ActivatorCache = activatorCache; } // cache the ctor ActivatorCacheEntry ace = new ActivatorCacheEntry(this, runtime_ctor, bNeedSecurityCheck); System.Threading.Thread.MemoryBarrier(); activatorCache.SetEntry(ace); } return instance; } [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] internal Object CreateInstanceImpl(bool publicOnly) { return CreateInstanceImpl(publicOnly, false, true); } [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] internal Object CreateInstanceImpl(bool publicOnly, bool skipVisibilityChecks, bool fillCache) { // next line will throw for ReflectionOnly types RuntimeTypeHandle typeHandle = TypeHandle; ActivatorCache activatorCache = s_ActivatorCache; if (activatorCache != null) { ActivatorCacheEntry ace = activatorCache.GetEntry(this); if (ace != null) { if (publicOnly) { if (ace.m_ctor != null && (ace.m_hCtorMethodHandle.GetAttributes() & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) { throw new MissingMethodException(Environment.GetResourceString("Arg_NoDefCTor")); } } // Allocate empty object Object instance = typeHandle.Allocate(); if (ace.m_ctor != null) { // Perform security checks if needed if (!skipVisibilityChecks && ace.m_bNeedSecurityCheck) { MethodBase.PerformSecurityCheck(instance, ace.m_hCtorMethodHandle, TypeHandle.Value, INVOCATION_FLAGS_CONSTRUCTOR_INVOKE); } // Call ctor (value types wont have any) try { ace.m_ctor(instance); } catch (Exception e) { throw new TargetInvocationException(e); } } return instance; } } return CreateInstanceSlow(publicOnly, fillCache); } //End internal bool SupportsInterface(Object o) { return TypeHandle.SupportsInterface(o); } internal void InvalidateCachedNestedType() { Cache.InvalidateCachedNestedType(); } internal bool IsGenericCOMObjectImpl() { return m_handle.IsComObject(true); } #endregion #region Legacy Static Internal internal static bool CanCastTo(RuntimeType fromType, RuntimeType toType) { return fromType.GetTypeHandleInternal().CanCastTo(toType.GetTypeHandleInternal()); } [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern Object _CreateEnum(IntPtr enumType, long value); internal static Object CreateEnum(RuntimeTypeHandle enumType, long value) { return _CreateEnum(enumType.Value, value); } #if FEATURE_COMINTEROP [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern Object InvokeDispMethod( String name, BindingFlags invokeAttr, Object target, Object[] args, bool[] byrefModifiers, int culture, String[] namedParameters); [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError); [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError); #endif internal static Type PrivateGetType(String typeName, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark) { return PrivateGetType(typeName, throwOnError, ignoreCase, false, ref stackMark); } internal static Type PrivateGetType(String typeName, bool throwOnError, bool ignoreCase, bool reflectionOnly, ref StackCrawlMark stackMark) { unsafe { if (typeName == null) throw new ArgumentNullException("TypeName"); return RuntimeTypeHandle.GetTypeByName( typeName, throwOnError, ignoreCase, reflectionOnly, ref stackMark).GetRuntimeType(); } } #endregion #region COM #if FEATURE_COMINTEROP private Object ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, int[] aWrapperTypes, ref MessageData msgData) { ParameterModifier[] aParamMod = null; Object ret = null; // Allocate a new message Message reqMsg = new Message(); reqMsg.InitFields(msgData); // Retrieve the required information from the message object. MethodInfo meth = (MethodInfo)reqMsg.GetMethodBase(); Object[] aArgs = reqMsg.Args; int cArgs = aArgs.Length; // Retrieve information from the method we are invoking on. ParameterInfo[] aParams = meth.GetParametersNoCopy(); // If we have arguments, then set the byref flags to true for byref arguments. // We also wrap the arguments that require wrapping. if (cArgs > 0) { ParameterModifier paramMod = new ParameterModifier(cArgs); for (int i = 0; i < cArgs; i++) { if (aParams[i].ParameterType.IsByRef) paramMod[i] = true; } aParamMod = new ParameterModifier[1]; aParamMod[0] = paramMod; if (aWrapperTypes != null) WrapArgsForInvokeCall(aArgs, aWrapperTypes); } // If the method has a void return type, then set the IgnoreReturn binding flag. if (meth.ReturnType == typeof(void)) flags |= BindingFlags.IgnoreReturn; try { // Invoke the method using InvokeMember(). ret = InvokeMember(memberName, flags, null, target, aArgs, aParamMod, null, null); } catch (TargetInvocationException e) { // For target invocation exceptions, we need to unwrap the inner exception and // re-throw it. throw e.InnerException; } // Convert each byref argument that is not of the proper type to // the parameter type using the OleAutBinder. for (int i = 0; i < cArgs; i++) { if (aParamMod[0][i] && aArgs[i] != null) { // The parameter is byref. Type paramType = aParams[i].ParameterType.GetElementType(); if (paramType != aArgs[i].GetType()) aArgs[i] = ForwardCallBinder.ChangeType(aArgs[i], paramType, null); } } // If the return type is not of the proper type, then convert it // to the proper type using the OleAutBinder. if (ret != null) { Type retType = meth.ReturnType; if (retType != ret.GetType()) ret = ForwardCallBinder.ChangeType(ret, retType, null); } // Propagate the out parameters RealProxy.PropagateOutParameters(reqMsg, aArgs, ret); // Return the value returned by the InvokeMember call. return ret; } private void WrapArgsForInvokeCall(Object[] aArgs, int[] aWrapperTypes) { int cArgs = aArgs.Length; for (int i = 0; i < cArgs; i++) { if (aWrapperTypes[i] == 0) continue; if (((DispatchWrapperType)aWrapperTypes[i] & DispatchWrapperType.SafeArray) != 0) { Type wrapperType = null; bool isString = false; // Determine the type of wrapper to use. switch ((DispatchWrapperType)aWrapperTypes[i] & ~DispatchWrapperType.SafeArray) { case DispatchWrapperType.Unknown: wrapperType = typeof(UnknownWrapper); break; case DispatchWrapperType.Dispatch: wrapperType = typeof(DispatchWrapper); break; case DispatchWrapperType.Error: wrapperType = typeof(ErrorWrapper); break; case DispatchWrapperType.Currency: wrapperType = typeof(CurrencyWrapper); break; case DispatchWrapperType.BStr: wrapperType = typeof(BStrWrapper); isString = true; break; default: BCLDebug.Assert(false, "[RuntimeType.WrapArgsForInvokeCall]Invalid safe array wrapper type specified."); break; } // Allocate the new array of wrappers. Array oldArray = (Array)aArgs[i]; int numElems = oldArray.Length; Object[] newArray = (Object[])Array.CreateInstance(wrapperType, numElems); // Retrieve the ConstructorInfo for the wrapper type. ConstructorInfo wrapperCons; if(isString) { wrapperCons = wrapperType.GetConstructor(new Type[] {typeof(String)}); } else { wrapperCons = wrapperType.GetConstructor(new Type[] {typeof(Object)}); } // Wrap each of the elements of the array. for (int currElem = 0; currElem < numElems; currElem++) { if(isString) { newArray[currElem] = wrapperCons.Invoke(new Object[] {(String)oldArray.GetValue(currElem)}); } else { newArray[currElem] = wrapperCons.Invoke(new Object[] {oldArray.GetValue(currElem)}); } } // Update the argument. aArgs[i] = newArray; } else { // Determine the wrapper to use and then wrap the argument. switch ((DispatchWrapperType)aWrapperTypes[i]) { case DispatchWrapperType.Unknown: aArgs[i] = new UnknownWrapper(aArgs[i]); break; case DispatchWrapperType.Dispatch: aArgs[i] = new DispatchWrapper(aArgs[i]); break; case DispatchWrapperType.Error: aArgs[i] = new ErrorWrapper(aArgs[i]); break; case DispatchWrapperType.Currency: aArgs[i] = new CurrencyWrapper(aArgs[i]); break; case DispatchWrapperType.BStr: aArgs[i] = new BStrWrapper((String)aArgs[i]); break; default: BCLDebug.Assert(false, "[RuntimeType.WrapArgsForInvokeCall]Invalid wrapper type specified."); break; } } } } private OleAutBinder ForwardCallBinder { get { // Synchronization is not required. if (s_ForwardCallBinder == null) s_ForwardCallBinder = new OleAutBinder(); return s_ForwardCallBinder; } } [Flags] private enum DispatchWrapperType : int { // This enum must stay in sync with the DispatchWrapperType enum defined in MLInfo.h Unknown = 0x00000001, Dispatch = 0x00000002, Record = 0x00000004, Error = 0x00000008, Currency = 0x00000010, BStr = 0x00000020, SafeArray = 0x00010000 } private static OleAutBinder s_ForwardCallBinder; #endif // FEATURE_COMINTEROP #endregion } // this is the introspection only type. This type overrides all the functions with runtime semantics // and throws an exception. // The idea behind this type is that it relieves RuntimeType from doing honerous checks about ReflectionOnly // context. // This type should not derive from RuntimeType but it's doing so for convinience. // That should not present a security threat though it is risky as a direct call to one of the base method // method (RuntimeType) and an instance of this type will work around the reason to have this type in the // first place. However given RuntimeType is not public all its methods are protected and require full trust // to be accessed [Serializable()] internal class ReflectionOnlyType : RuntimeType { private ReflectionOnlyType() {} // always throw public override RuntimeTypeHandle TypeHandle { get { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly")); } } } namespace Reflection { [Serializable] internal sealed class CerArrayList { private const int MinSize = 4; private V[] m_array; private int m_count; [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal CerArrayList(List list) { m_array = new V[list.Count]; for (int i = 0; i < list.Count; i ++) m_array[i] = list[i]; m_count = list.Count; } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal CerArrayList(int length) { if (length < MinSize) length = MinSize; m_array = new V[length]; m_count = 0; } internal int Count { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { return m_count; } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal void Preallocate(int addition) { if (m_array.Length - m_count > addition) return; int newSize = m_array.Length * 2 > m_array.Length + addition ? m_array.Length * 2 : m_array.Length + addition; V[] newArray = new V[newSize]; for (int i = 0; i < m_count; i++) { newArray[i] = m_array[i]; } m_array = newArray; } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal void Add(V value) { m_array[m_count] = value; m_count++; } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal void Replace(int index, V value) { if (index >= m_count) throw new InvalidOperationException(); m_array[index] = value; } internal V this[int index] { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { return m_array[index]; } } } [Serializable] internal sealed class CerHashtable { private K[] m_key; private V[] m_value; private int m_count; private const int MinSize = 7; [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal CerHashtable() : this(MinSize) { } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal CerHashtable(int size) { size = HashHelpers.GetPrime(size); m_key = new K[size]; m_value = new V[size]; } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal void Preallocate(int count) { bool tookLock = false; bool success = false; K[] newKeys = null;; V[] newValues = null; RuntimeHelpers.PrepareConstrainedRegions(); try { Monitor.ReliableEnter(this, ref tookLock); int newSize = (count + m_count) * 2; if (newSize < m_value.Length) return; newSize = HashHelpers.GetPrime(newSize); newKeys = new K[newSize]; newValues = new V[newSize]; for (int i = 0; i < m_key.Length; i++) { K key = m_key[i]; if (key != null) { int dummyCount = 0; Insert(newKeys, newValues, ref dummyCount, key, m_value[i]); } } success = true; } finally { if (success) { m_key = newKeys; m_value = newValues; } if (tookLock) Monitor.Exit(this); } } // Written as a static so we can share this code from Set and // Preallocate, which adjusts the data structure in place. // Returns whether we inserted the item into a new slot or reused // an existing hash table bucket. // Reliability-wise, we don't guarantee that the updates to the key // and value arrays are done atomically within a CER. Either // add your own CER or use temporary copies of this data structure. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static void Insert(K[] keys, V[] values, ref int count, K key, V value) { int hashcode = key.GetHashCode(); if (hashcode < 0) hashcode = -hashcode; int firstIndex = hashcode % keys.Length; int index = firstIndex; while (true) { K hit = keys[index]; if ((object)hit == null) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { keys[index] = key; values[index] = value; count++; } break; } else if (hit.Equals(key)) // Replace existing item { //BCLDebug.Assert(false, "Key was already in CerHashtable! Potential race (or throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate__", hit, key)); // If we wanted to make this more general, do this: /* values[index] = value; usedNewSlot = false; */ //break; } else { index++; index %= keys.Length; } } } internal V this[K key] { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] set { bool tookLock = false; RuntimeHelpers.PrepareConstrainedRegions(); try { Monitor.ReliableEnter(this, ref tookLock); Insert(m_key, m_value, ref m_count, key, value); } finally { if (tookLock) Monitor.Exit(this); } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] get { bool tookLock = false; RuntimeHelpers.PrepareConstrainedRegions(); try { Monitor.ReliableEnter(this, ref tookLock); int hashcode = key.GetHashCode(); if (hashcode < 0) hashcode = -hashcode; int firstIndex = hashcode % m_key.Length; int index = firstIndex; while (true) { K hit = m_key[index]; if ((object)hit != null) { if (hit.Equals(key)) return m_value[index]; index++; index %= m_key.Length; } else { return default(V); } } } finally { if (tookLock) Monitor.Exit(this); } } } } } #region Library internal unsafe struct Utf8String { [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern unsafe bool EqualsCaseSensitive(void* szLhs, void* szRhs, int cSz); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern unsafe bool EqualsCaseInsensitive(void* szLhs, void* szRhs, int cSz); private static int GetUtf8StringByteLength(void* pUtf8String) { int len = 0; unsafe { byte * pItr = (byte*)pUtf8String; while (*pItr != 0) { len++; pItr++; } } return len; } private void* m_pStringHeap; // This is the raw UTF8 string. private int m_StringHeapByteLength; internal Utf8String(void* pStringHeap) { m_pStringHeap = pStringHeap; if (pStringHeap != null) { m_StringHeapByteLength = GetUtf8StringByteLength(pStringHeap); } else { m_StringHeapByteLength = 0; } } internal unsafe Utf8String(void* pUtf8String, int cUtf8String) { m_pStringHeap = pUtf8String; m_StringHeapByteLength = cUtf8String; } internal unsafe bool Equals(Utf8String s) { if (m_pStringHeap == null) { return s.m_StringHeapByteLength == 0; } if ((s.m_StringHeapByteLength == m_StringHeapByteLength) && (m_StringHeapByteLength != 0)) { return Utf8String.EqualsCaseSensitive(s.m_pStringHeap, m_pStringHeap, m_StringHeapByteLength); } return false; } internal unsafe bool EqualsCaseInsensitive(Utf8String s) { if (m_pStringHeap == null) { return s.m_StringHeapByteLength == 0; } if ((s.m_StringHeapByteLength == m_StringHeapByteLength) && (m_StringHeapByteLength != 0)) { return Utf8String.EqualsCaseInsensitive(s.m_pStringHeap, m_pStringHeap, m_StringHeapByteLength); } return false; } public override string ToString() { unsafe { byte* buf = stackalloc byte[m_StringHeapByteLength]; byte * pItr = (byte*)m_pStringHeap; for (int currentPos = 0; currentPos < m_StringHeapByteLength; currentPos++) { buf[currentPos] = *pItr; pItr++; } if (m_StringHeapByteLength == 0) return ""; int cResult = Encoding.UTF8.GetCharCount(buf, m_StringHeapByteLength); char* result = stackalloc char[cResult]; Encoding.UTF8.GetChars(buf, m_StringHeapByteLength, result, cResult); return new string(result, 0, cResult); } } } internal sealed class ASSERT : Exception { #region FRIEND private static bool AssertIsFriend(Type[] friends, StackTrace st) { Type typeOfCallee = st.GetFrame(1).GetMethod().DeclaringType; Type typeOfCaller = st.GetFrame(2).GetMethod().DeclaringType; bool noFriends = true; foreach(Type friend in friends) { if (typeOfCaller != friend && typeOfCaller != typeOfCallee) noFriends = false; } if (noFriends) Assert(false, Environment.GetResourceString("RtType.InvalidCaller"), st.ToString()); return true; } [Conditional("_DEBUG")] internal static void FRIEND(Type[] friends) { StackTrace st = new StackTrace(); AssertIsFriend(friends, st); } [Conditional("_DEBUG")] internal static void FRIEND(Type friend) { StackTrace st = new StackTrace(); AssertIsFriend(new Type[] {friend}, st); } [Conditional("_DEBUG")] internal static void FRIEND(string ns) { StackTrace st = new StackTrace(); string nsOfCallee = st.GetFrame(1).GetMethod().DeclaringType.Namespace; string nsOfCaller = st.GetFrame(2).GetMethod().DeclaringType.Namespace; Assert(nsOfCaller.Equals(nsOfCaller) || nsOfCaller.Equals(ns), Environment.GetResourceString("RtType.InvalidCaller"), st.ToString()); } #endregion #region PRECONDITION [Conditional("_DEBUG")] internal static void PRECONDITION(bool condition) { Assert(condition); } [Conditional("_DEBUG")] internal static void PRECONDITION(bool condition, string message) { Assert(condition, message); } [Conditional("_DEBUG")] internal static void PRECONDITION(bool condition, string message, string detailedMessage) { Assert(condition, message, detailedMessage); } #endregion #region POSTCONDITION [Conditional("_DEBUG")] internal static void POSTCONDITION(bool condition) { Assert(condition); } [Conditional("_DEBUG")] internal static void POSTCONDITION(bool condition, string message) { Assert(condition, message); } [Conditional("_DEBUG")] internal static void POSTCONDITION(bool condition, string message, string detailedMessage) { Assert(condition, message, detailedMessage); } #endregion #region CONSISTENCY_CHECK [Conditional("_DEBUG")] internal static void CONSISTENCY_CHECK(bool condition) { Assert(condition); } [Conditional("_DEBUG")] internal static void CONSISTENCY_CHECK(bool condition, string message) { Assert(condition, message); } [Conditional("_DEBUG")] internal static void CONSISTENCY_CHECK(bool condition, string message, string detailedMessage) { Assert(condition, message, detailedMessage); } #endregion #region SIMPLIFYING_ASSUMPTION [Conditional("_DEBUG")] internal static void SIMPLIFYING_ASSUMPTION(bool condition) { Assert(condition); } [Conditional("_DEBUG")] internal static void SIMPLIFYING_ASSUMPTION(bool condition, string message) { Assert(condition, message); } [Conditional("_DEBUG")] internal static void SIMPLIFYING_ASSUMPTION(bool condition, string message, string detailedMessage) { Assert(condition, message, detailedMessage); } #endregion #region UNREACHABLE [Conditional("_DEBUG")] internal static void UNREACHABLE() { Assert(); } [Conditional("_DEBUG")] internal static void UNREACHABLE(string message) { Assert(message); } [Conditional("_DEBUG")] internal static void UNREACHABLE(string message, string detailedMessage) { Assert(message, detailedMessage); } #endregion #region NOT_IMPLEMENTED [Conditional("_DEBUG")] internal static void NOT_IMPLEMENTED() { Assert(); } [Conditional("_DEBUG")] internal static void NOT_IMPLEMENTED(string message) { Assert(message); } [Conditional("_DEBUG")] internal static void NOT_IMPLEMENTED(string message, string detailedMessage) { Assert(message, detailedMessage); } #endregion #region Private Asserts - Throw before assertt so debugger can inspect private static void Assert() { Assert(false, null, null); } private static void Assert(string message) { Assert(false, message, null); } private static void Assert(bool condition) { Assert(condition, null, null); } private static void Assert(bool condition, string message) { Assert(condition, message, null); } private static void Assert(string message, string detailedMessage) { Assert(false, message, detailedMessage); } private static void Assert(bool condition, string message, string detailedMessage) { if (!condition) { // Console.WriteLine("ASSERT MESSAGE: " + message + ", " + detailedMessage); // System.Diagnostics.Debug.Assert(condition, message, detailedMessage); // throw new ASSERT(); } } #endregion } internal static class LOGIC { internal static bool IMPLIES(bool p, bool q) { return !p || q; } internal static bool BIJECTION(bool p, bool q) { return IMPLIES(p,q) && IMPLIES(q,p); } } #endregion } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Schema.cs
- XmlSchemaGroupRef.cs
- SerializationEventsCache.cs
- AudioBase.cs
- SqlUserDefinedTypeAttribute.cs
- DbgCompiler.cs
- TransformGroup.cs
- IUnknownConstantAttribute.cs
- Image.cs
- PipelineModuleStepContainer.cs
- PreloadedPackages.cs
- WindowCollection.cs
- PolyQuadraticBezierSegment.cs
- ProviderIncompatibleException.cs
- XXXInfos.cs
- ButtonBase.cs
- MailWriter.cs
- HostingEnvironmentException.cs
- EnumValAlphaComparer.cs
- HttpInputStream.cs
- RemoteWebConfigurationHostStream.cs
- AlphabeticalEnumConverter.cs
- ApplicationBuildProvider.cs
- RoutedPropertyChangedEventArgs.cs
- Errors.cs
- RegionInfo.cs
- X509Certificate.cs
- recordstatefactory.cs
- FixedSOMTableCell.cs
- ThousandthOfEmRealDoubles.cs
- SerializationObjectManager.cs
- MultiAsyncResult.cs
- ApplicationProxyInternal.cs
- WizardForm.cs
- ChangeToolStripParentVerb.cs
- Content.cs
- ProcessThreadCollection.cs
- ProcessThreadDesigner.cs
- SessionPageStateSection.cs
- Signature.cs
- WebPartConnectionCollection.cs
- LocatorPart.cs
- PerformanceCounterLib.cs
- wpf-etw.cs
- DefaultShape.cs
- FrameworkTemplate.cs
- LinqDataView.cs
- FontStretches.cs
- ConnectionConsumerAttribute.cs
- EntityDataSourceMemberPath.cs
- ExpressionBinding.cs
- TextWriter.cs
- InfoCardRequestException.cs
- WebBrowserBase.cs
- TypeDescriptionProvider.cs
- RightsManagementEncryptionTransform.cs
- ColumnMapProcessor.cs
- CompositeDuplexBindingElementImporter.cs
- InstancePersistenceEvent.cs
- MessageFilterException.cs
- MouseActionValueSerializer.cs
- DataControlPagerLinkButton.cs
- XmlHierarchicalEnumerable.cs
- EdmProviderManifest.cs
- AppDomainShutdownMonitor.cs
- ColorConverter.cs
- dataSvcMapFileLoader.cs
- RijndaelManaged.cs
- ToolTip.cs
- UInt16.cs
- FocusManager.cs
- TriggerCollection.cs
- DbBuffer.cs
- MethodRental.cs
- DataTableReaderListener.cs
- SafeLocalMemHandle.cs
- EntityTemplateFactory.cs
- SymmetricKeyWrap.cs
- SqlDataAdapter.cs
- HyperLinkDataBindingHandler.cs
- RotateTransform.cs
- RoleService.cs
- TriState.cs
- PermissionAttributes.cs
- BindingNavigatorDesigner.cs
- HashCryptoHandle.cs
- WindowsPen.cs
- ActivityExecutor.cs
- WebPartVerbsEventArgs.cs
- MembershipSection.cs
- cookie.cs
- ValueUtilsSmi.cs
- ImmComposition.cs
- TableStyle.cs
- LabelEditEvent.cs
- ConstraintManager.cs
- DragDrop.cs
- CodeSnippetStatement.cs
- CodeEntryPointMethod.cs
- SmtpTransport.cs