summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/RtType.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/RtType.cs')
-rw-r--r--src/mscorlib/src/System/RtType.cs5862
1 files changed, 5862 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/RtType.cs b/src/mscorlib/src/System/RtType.cs
new file mode 100644
index 0000000000..037576fc33
--- /dev/null
+++ b/src/mscorlib/src/System/RtType.cs
@@ -0,0 +1,5862 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+//
+// Implements System.RuntimeType
+//
+// ======================================================================================
+
+
+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;
+using System.Runtime.Serialization;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Runtime.Remoting;
+#if FEATURE_REMOTING
+using System.Runtime.Remoting.Proxies;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Activation;
+using System.Runtime.Remoting.Metadata;
+#endif
+using MdSigCallingConvention = System.Signature.MdSigCallingConvention;
+using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
+using System.Runtime.InteropServices;
+using DebuggerStepThroughAttribute = System.Diagnostics.DebuggerStepThroughAttribute;
+using MdToken = System.Reflection.MetadataToken;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+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);
+
+ // Keep this in sync with FormatFlags defined in typestring.h
+ internal enum TypeNameFormatFlags
+ {
+ FormatBasic = 0x00000000, // Not a bitmask, simply the tersest flag settings possible
+ FormatNamespace = 0x00000001, // Include namespace and/or enclosing class names in type names
+ FormatFullInst = 0x00000002, // Include namespace and assembly in generic types (regardless of other flag settings)
+ FormatAssembly = 0x00000004, // Include assembly display name in type names
+ FormatSignature = 0x00000008, // Include signature in method names
+ FormatNoVersion = 0x00000010, // Suppress version and culture information in all assembly names
+#if _DEBUG
+ FormatDebug = 0x00000020, // For debug printing of types only
+#endif
+ FormatAngleBrackets = 0x00000040, // Whether generic types are C<T> or C[T]
+ FormatStubInfo = 0x00000080, // Include stub info like {unbox-stub}
+ FormatGenericParam = 0x00000100, // Use !name and !!name for generic type and method parameters
+
+ // If we want to be able to distinguish between overloads whose parameter types have the same name but come from different assemblies,
+ // we can add FormatAssembly | FormatNoVersion to FormatSerialization. But we are omitting it because it is not a useful scenario
+ // and including the assembly name will normally increase the size of the serialized data and also decrease the performance.
+ FormatSerialization = FormatNamespace |
+ FormatGenericParam |
+ FormatFullInst
+ }
+
+ internal enum TypeNameKind
+ {
+ Name,
+ ToString,
+ SerializationName,
+ FullName,
+ }
+
+ [Serializable]
+ internal class RuntimeType :
+ System.Reflection.TypeInfo, ISerializable, ICloneable
+ {
+ #region Definitions
+
+ internal enum MemberListType
+ {
+ All,
+ CaseSensitive,
+ CaseInsensitive,
+ HandleToInfo
+ }
+
+ // Helper to build lists of MemberInfos. Special cased to avoid allocations for lists of one element.
+ private struct ListBuilder<T> where T : class
+ {
+ T[] _items;
+ T _item;
+ int _count;
+ int _capacity;
+
+ public ListBuilder(int capacity)
+ {
+ _items = null;
+ _item = null;
+ _count = 0;
+ _capacity = capacity;
+ }
+
+ public T this[int index]
+ {
+ get
+ {
+ Contract.Requires(index < Count);
+ return (_items != null) ? _items[index] : _item;
+ }
+ }
+
+ public T[] ToArray()
+ {
+ if (_count == 0)
+ return EmptyArray<T>.Value;
+ if (_count == 1)
+ return new T[1] { _item };
+
+ Array.Resize(ref _items, _count);
+ _capacity = _count;
+ return _items;
+ }
+
+ public void CopyTo(Object[] array, int index)
+ {
+ if (_count == 0)
+ return;
+
+ if (_count == 1)
+ {
+ array[index] = _item;
+ return;
+ }
+
+ Array.Copy(_items, 0, array, index, _count);
+ }
+
+ public int Count
+ {
+ get
+ {
+ return _count;
+ }
+ }
+
+ public void Add(T item)
+ {
+ if (_count == 0)
+ {
+ _item = item;
+ }
+ else
+ {
+ if (_count == 1)
+ {
+ if (_capacity < 2)
+ _capacity = 4;
+ _items = new T[_capacity];
+ _items[0] = _item;
+ }
+ else
+ if (_capacity == _count)
+ {
+ int newCapacity = 2 * _capacity;
+ Array.Resize(ref _items, newCapacity);
+ _capacity = newCapacity;
+ }
+
+ _items[_count] = item;
+ }
+ _count++;
+ }
+ }
+
+ internal class RuntimeTypeCache
+ {
+ private const int MAXNAMELEN = 1024;
+
+ #region Definitions
+ internal enum CacheType
+ {
+ Method,
+ Constructor,
+ Field,
+ Property,
+ Event,
+ Interface,
+ NestedType
+ }
+
+ private struct Filter
+ {
+ private Utf8String m_name;
+ private MemberListType m_listType;
+ private uint m_nameHash;
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe Filter(byte* pUtf8Name, int cUtf8Name, MemberListType listType)
+ {
+ this.m_name = new Utf8String((void*) pUtf8Name, cUtf8Name);
+ this.m_listType = listType;
+ this.m_nameHash = 0;
+
+ if (RequiresStringComparison())
+ {
+ m_nameHash = m_name.HashCaseInsensitive();
+ }
+ }
+
+ public bool Match(Utf8String name)
+ {
+ bool retVal = true;
+
+ if (m_listType == MemberListType.CaseSensitive)
+ retVal = m_name.Equals(name);
+ else if (m_listType == MemberListType.CaseInsensitive)
+ retVal = m_name.EqualsCaseInsensitive(name);
+
+ // Currently the callers of UsesStringComparison assume that if it returns false
+ // then the match always succeeds and can be skipped. Assert that this is maintained.
+ Contract.Assert(retVal || RequiresStringComparison());
+
+ return retVal;
+ }
+
+ // Does the current match type require a string comparison?
+ // If not, we know Match will always return true and the call can be skipped
+ // If so, we know we can have a valid hash to check against from GetHashToMatch
+ public bool RequiresStringComparison()
+ {
+ return (m_listType == MemberListType.CaseSensitive) ||
+ (m_listType == MemberListType.CaseInsensitive);
+ }
+
+ public bool CaseSensitive()
+ {
+ return (m_listType == MemberListType.CaseSensitive);
+ }
+
+ public uint GetHashToMatch()
+ {
+ Contract.Assert(RequiresStringComparison());
+
+ return m_nameHash;
+ }
+ }
+
+ private class MemberInfoCache<T> where T : MemberInfo
+ {
+ #region Private Data Members
+
+ // MemberInfo caches
+ private CerHashtable<string, T[]> m_csMemberInfos;
+ private CerHashtable<string, T[]> m_cisMemberInfos;
+ // List of MemberInfos given out. When m_cacheComplete is false, it may have null entries at the end to avoid
+ // reallocating the list every time a new entry is added.
+ private T[] m_allMembers;
+ private bool m_cacheComplete;
+
+ // This is the strong reference back to the cache
+ private RuntimeTypeCache m_runtimeTypeCache;
+ #endregion
+
+ #region Constructor
+#if MDA_SUPPORTED
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ internal MemberInfoCache(RuntimeTypeCache runtimeTypeCache)
+ {
+#if MDA_SUPPORTED
+ Mda.MemberInfoCacheCreation();
+#endif
+ m_runtimeTypeCache = runtimeTypeCache;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal MethodBase AddMethod(RuntimeType declaringType, RuntimeMethodHandleInternal method, CacheType cacheType)
+ {
+ T[] list = null;
+ MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(method);
+ bool isPublic = (methodAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
+ bool isStatic = (methodAttributes & MethodAttributes.Static) != 0;
+ bool isInherited = declaringType != ReflectedType;
+ BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic);
+ switch (cacheType)
+ {
+ case CacheType.Method:
+ list = (T[])(object)new RuntimeMethodInfo[1] {
+ new RuntimeMethodInfo(method, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null)
+ };
+ break;
+ case CacheType.Constructor:
+ list = (T[])(object)new RuntimeConstructorInfo[1] {
+ new RuntimeConstructorInfo(method, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags)
+ };
+ break;
+ }
+
+ Insert(ref list, null, MemberListType.HandleToInfo);
+
+ return (MethodBase)(object)list[0];
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal FieldInfo AddField(RuntimeFieldHandleInternal field)
+ {
+ // create the runtime field info
+ FieldAttributes fieldAttributes = RuntimeFieldHandle.GetAttributes(field);
+ bool isPublic = (fieldAttributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public;
+ bool isStatic = (fieldAttributes & FieldAttributes.Static) != 0;
+ RuntimeType approxDeclaringType = RuntimeFieldHandle.GetApproxDeclaringType(field);
+ bool isInherited = RuntimeFieldHandle.AcquiresContextFromThis(field) ?
+ !RuntimeTypeHandle.CompareCanonicalHandles(approxDeclaringType, ReflectedType) :
+ approxDeclaringType != ReflectedType;
+
+ BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic);
+
+ T[] list = (T[])(object)new RuntimeFieldInfo[1] {
+ new RtFieldInfo(field, ReflectedType, m_runtimeTypeCache, bindingFlags)
+ };
+
+ Insert(ref list, null, MemberListType.HandleToInfo);
+
+ return (FieldInfo)(object)list[0];
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe T[] Populate(string name, MemberListType listType, CacheType cacheType)
+ {
+ T[] list = null;
+
+ if (name == null || name.Length == 0 ||
+ (cacheType == CacheType.Constructor && name.FirstChar != '.' && name.FirstChar != '*'))
+ {
+ list = GetListByName(null, 0, null, 0, listType, cacheType);
+ }
+ else
+ {
+ int cNameLen = name.Length;
+ fixed (char* pName = name)
+ {
+ int cUtf8Name = Encoding.UTF8.GetByteCount(pName, cNameLen);
+ // allocating on the stack is faster than allocating on the GC heap
+ // but we surely don't want to cause a stack overflow
+ // no one should be looking for a member whose name is longer than 1024
+ if (cUtf8Name > MAXNAMELEN)
+ {
+ fixed (byte* pUtf8Name = new byte[cUtf8Name])
+ {
+ list = GetListByName(pName, cNameLen, pUtf8Name, cUtf8Name, listType, cacheType);
+ }
+ }
+ else
+ {
+ byte* pUtf8Name = stackalloc byte[cUtf8Name];
+ list = GetListByName(pName, cNameLen, pUtf8Name, cUtf8Name, listType, cacheType);
+ }
+ }
+ }
+
+ Insert(ref list, name, listType);
+
+ return list;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe T[] GetListByName(char* pName, int cNameLen, byte* pUtf8Name, int cUtf8Name, MemberListType listType, CacheType cacheType)
+ {
+ if (cNameLen != 0)
+ Encoding.UTF8.GetBytes(pName, cNameLen, pUtf8Name, cUtf8Name);
+
+ Filter filter = new Filter(pUtf8Name, cUtf8Name, listType);
+ Object list = null;
+
+ switch (cacheType)
+ {
+ case CacheType.Method:
+ list = PopulateMethods(filter);
+ break;
+ case CacheType.Field:
+ list = PopulateFields(filter);
+ break;
+ case CacheType.Constructor:
+ list = PopulateConstructors(filter);
+ break;
+ case CacheType.Property:
+ list = PopulateProperties(filter);
+ break;
+ case CacheType.Event:
+ list = PopulateEvents(filter);
+ break;
+ case CacheType.NestedType:
+ list = PopulateNestedClasses(filter);
+ break;
+ case CacheType.Interface:
+ list = PopulateInterfaces(filter);
+ break;
+ default:
+ BCLDebug.Assert(false, "Invalid CacheType");
+ break;
+ }
+
+ return (T[])list;
+ }
+
+ // 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.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal void Insert(ref T[] list, string name, MemberListType listType)
+ {
+ bool lockTaken = false;
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(this, ref lockTaken);
+
+ switch (listType)
+ {
+ case MemberListType.CaseSensitive:
+ {
+ // Ensure we always return a list that has
+ // been merged with the global list.
+ T[] cachedList = m_csMemberInfos[name];
+ if (cachedList == null)
+ {
+ MergeWithGlobalList(list);
+ m_csMemberInfos[name] = list;
+ }
+ else
+ list = cachedList;
+ }
+ break;
+
+ case MemberListType.CaseInsensitive:
+ {
+ // Ensure we always return a list that has
+ // been merged with the global list.
+ T[] cachedList = m_cisMemberInfos[name];
+ if (cachedList == null)
+ {
+ MergeWithGlobalList(list);
+ m_cisMemberInfos[name] = list;
+ }
+ else
+ list = cachedList;
+ }
+ break;
+
+ case MemberListType.All:
+ if (!m_cacheComplete)
+ {
+ MergeWithGlobalList(list);
+
+ // Trim null entries at the end of m_allMembers array
+ int memberCount = m_allMembers.Length;
+ while (memberCount > 0)
+ {
+ if (m_allMembers[memberCount-1] != null)
+ break;
+ memberCount--;
+ }
+ Array.Resize(ref m_allMembers, memberCount);
+
+ Volatile.Write(ref m_cacheComplete, true);
+ }
+ else
+ list = m_allMembers;
+ break;
+
+ default:
+ MergeWithGlobalList(list);
+ break;
+ }
+ }
+ finally
+ {
+ if (lockTaken)
+ {
+ Monitor.Exit(this);
+ }
+ }
+ }
+
+ // Modifies the existing list.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private void MergeWithGlobalList(T[] list)
+ {
+ T[] cachedMembers = m_allMembers;
+
+ if (cachedMembers == null)
+ {
+ m_allMembers = list;
+ return;
+ }
+
+ int cachedCount = cachedMembers.Length;
+ int freeSlotIndex = 0;
+
+ for (int i = 0; i < list.Length; i++)
+ {
+ T newMemberInfo = list[i];
+ bool foundInCache = false;
+
+ int cachedIndex;
+ for (cachedIndex = 0; cachedIndex < cachedCount; cachedIndex++)
+ {
+ T cachedMemberInfo = cachedMembers[cachedIndex];
+ if (cachedMemberInfo == null)
+ break;
+
+ if (newMemberInfo.CacheEquals(cachedMemberInfo))
+ {
+ list[i] = cachedMemberInfo;
+ foundInCache = true;
+ break;
+ }
+ }
+
+ if (!foundInCache)
+ {
+ if (freeSlotIndex == 0)
+ freeSlotIndex = cachedIndex;
+
+ if (freeSlotIndex >= cachedMembers.Length)
+ {
+ int newSize;
+ if (m_cacheComplete)
+ {
+ //
+ // In theory, we should never add more elements to the cache when it is complete.
+ //
+ // Unfortunately, we shipped with bugs that cause changes of the complete cache (DevDiv #339308).
+ // Grow the list by exactly one element in this case to avoid null entries at the end.
+ //
+
+ Contract.Assert(false);
+
+ newSize = cachedMembers.Length + 1;
+ }
+ else
+ {
+ newSize = Math.Max(Math.Max(4, 2 * cachedMembers.Length), list.Length);
+ }
+
+ // Use different variable for ref argument to Array.Resize to allow enregistration of cachedMembers by the JIT
+ T[] cachedMembers2 = cachedMembers;
+ Array.Resize(ref cachedMembers2, newSize);
+ cachedMembers = cachedMembers2;
+ }
+
+ Contract.Assert(cachedMembers[freeSlotIndex] == null);
+ cachedMembers[freeSlotIndex] = newMemberInfo;
+ freeSlotIndex++;
+ }
+ }
+
+ m_allMembers = cachedMembers;
+ }
+ #endregion
+
+ #region Population Logic
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe RuntimeMethodInfo[] PopulateMethods(Filter filter)
+ {
+ ListBuilder<RuntimeMethodInfo> list = new ListBuilder<RuntimeMethodInfo>();
+
+ RuntimeType declaringType = ReflectedType;
+ Contract.Assert(declaringType != null);
+
+ if (RuntimeTypeHandle.IsInterface(declaringType))
+ {
+ #region IsInterface
+
+ foreach (RuntimeMethodHandleInternal methodHandle in RuntimeTypeHandle.GetIntroducedMethods(declaringType))
+ {
+ if (filter.RequiresStringComparison())
+ {
+ if (!RuntimeMethodHandle.MatchesNameHash(methodHandle, filter.GetHashToMatch()))
+ {
+ Contract.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)));
+ continue;
+ }
+
+ if (!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)))
+ continue;
+ }
+
+ #region Loop through all methods on the interface
+ Contract.Assert(!methodHandle.IsNullHandle());
+ // Except for .ctor, .cctor, IL_STUB*, and static methods, all interface methods should be abstract, virtual, and non-RTSpecialName.
+ // Note that this assumption will become invalid when we add support for non-abstract or static methods on interfaces.
+ Contract.Assert(
+ (RuntimeMethodHandle.GetAttributes(methodHandle) & (MethodAttributes.RTSpecialName | MethodAttributes.Abstract | MethodAttributes.Virtual)) == (MethodAttributes.Abstract | MethodAttributes.Virtual) ||
+ (RuntimeMethodHandle.GetAttributes(methodHandle) & MethodAttributes.Static) == MethodAttributes.Static ||
+ RuntimeMethodHandle.GetName(methodHandle).Equals(".ctor") ||
+ RuntimeMethodHandle.GetName(methodHandle).Equals(".cctor") ||
+ RuntimeMethodHandle.GetName(methodHandle).StartsWith("IL_STUB", StringComparison.Ordinal));
+
+ #region Calculate Binding Flags
+ MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(methodHandle);
+ 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)
+ continue;
+
+ // get the unboxing stub or instantiating stub if needed
+ RuntimeMethodHandleInternal instantiatedHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaringType, null);
+
+ RuntimeMethodInfo runtimeMethodInfo = new RuntimeMethodInfo(
+ instantiatedHandle, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null);
+
+ list.Add(runtimeMethodInfo);
+ #endregion
+ }
+ #endregion
+ }
+ else
+ {
+ #region IsClass or GenericParameter
+ while(RuntimeTypeHandle.IsGenericVariable(declaringType))
+ declaringType = declaringType.GetBaseType();
+
+ bool* overrides = stackalloc bool[RuntimeTypeHandle.GetNumVirtuals(declaringType)];
+ bool isValueType = declaringType.IsValueType;
+
+ do
+ {
+ int vtableSlots = RuntimeTypeHandle.GetNumVirtuals(declaringType);
+
+ foreach (RuntimeMethodHandleInternal methodHandle in RuntimeTypeHandle.GetIntroducedMethods(declaringType))
+ {
+ if (filter.RequiresStringComparison())
+ {
+ if (!RuntimeMethodHandle.MatchesNameHash(methodHandle, filter.GetHashToMatch()))
+ {
+ Contract.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)));
+ continue;
+ }
+
+ if (!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)))
+ continue;
+ }
+
+ #region Loop through all methods on the current type
+ Contract.Assert(!methodHandle.IsNullHandle());
+
+ MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(methodHandle);
+ MethodAttributes methodAccess = methodAttributes & MethodAttributes.MemberAccessMask;
+
+ #region Continue if this is a constructor
+ Contract.Assert(
+ (RuntimeMethodHandle.GetAttributes(methodHandle) & MethodAttributes.RTSpecialName) == 0 ||
+ RuntimeMethodHandle.GetName(methodHandle).Equals(".ctor") ||
+ RuntimeMethodHandle.GetName(methodHandle).Equals(".cctor"));
+
+ if ((methodAttributes & MethodAttributes.RTSpecialName) != 0)
+ 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
+ // assert if an EnC method, which can't be virtual, so narrow down first
+ // before calling GetSlot
+ methodSlot = RuntimeMethodHandle.GetSlot(methodHandle);
+ isVirtual = (methodSlot < vtableSlots);
+ }
+
+ bool isInherited = declaringType != ReflectedType;
+
+ bool isPrivate = methodAccess == MethodAttributes.Private;
+ if (isInherited && isPrivate && !isVirtual)
+ continue;
+
+ #endregion
+
+ #region Continue if this is a virtual and is already overridden
+ if (isVirtual)
+ {
+ Contract.Assert(
+ (methodAttributes & MethodAttributes.Abstract) != 0 ||
+ (methodAttributes & MethodAttributes.Virtual) != 0 ||
+ RuntimeMethodHandle.GetDeclaringType(methodHandle) != declaringType);
+
+ if (overrides[methodSlot] == true)
+ continue;
+
+ overrides[methodSlot] = true;
+ }
+ else if (isValueType)
+ {
+ if ((methodAttributes & (MethodAttributes.Virtual | MethodAttributes.Abstract)) != 0)
+ continue;
+ }
+ else
+ {
+ Contract.Assert((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
+
+ // get the unboxing stub or instantiating stub if needed
+ RuntimeMethodHandleInternal instantiatedHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaringType, null);
+
+ RuntimeMethodInfo runtimeMethodInfo = new RuntimeMethodInfo(
+ instantiatedHandle, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null);
+
+ list.Add(runtimeMethodInfo);
+ #endregion
+ }
+
+ declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
+ } while (declaringType != null);
+ #endregion
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private RuntimeConstructorInfo[] PopulateConstructors(Filter filter)
+ {
+ if (ReflectedType.IsGenericParameter)
+ {
+ return EmptyArray<RuntimeConstructorInfo>.Value;
+ }
+
+ ListBuilder<RuntimeConstructorInfo> list = new ListBuilder<RuntimeConstructorInfo>();
+
+ RuntimeType declaringType= ReflectedType;
+
+ foreach (RuntimeMethodHandleInternal methodHandle in RuntimeTypeHandle.GetIntroducedMethods(declaringType))
+ {
+ if (filter.RequiresStringComparison())
+ {
+ if (!RuntimeMethodHandle.MatchesNameHash(methodHandle, filter.GetHashToMatch()))
+ {
+ Contract.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)));
+ continue;
+ }
+
+ if (!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)))
+ continue;
+ }
+
+ MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(methodHandle);
+
+ Contract.Assert(!methodHandle.IsNullHandle());
+
+ if ((methodAttributes & MethodAttributes.RTSpecialName) == 0)
+ continue;
+
+ // Constructors should not be virtual or abstract
+ Contract.Assert(
+ (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
+
+ // get the unboxing stub or instantiating stub if needed
+ RuntimeMethodHandleInternal instantiatedHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaringType, null);
+
+ RuntimeConstructorInfo runtimeConstructorInfo =
+ new RuntimeConstructorInfo(instantiatedHandle, ReflectedType, m_runtimeTypeCache, methodAttributes, bindingFlags);
+
+ list.Add(runtimeConstructorInfo);
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe RuntimeFieldInfo[] PopulateFields(Filter filter)
+ {
+ ListBuilder<RuntimeFieldInfo> list = new ListBuilder<RuntimeFieldInfo>();
+
+ RuntimeType declaringType = ReflectedType;
+
+ #region Populate all static, instance and literal fields
+ while(RuntimeTypeHandle.IsGenericVariable(declaringType))
+ declaringType = declaringType.GetBaseType();
+
+ while(declaringType != null)
+ {
+ PopulateRtFields(filter, declaringType, ref list);
+
+ PopulateLiteralFields(filter, declaringType, ref list);
+
+ declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
+ }
+ #endregion
+
+ #region Populate Literal Fields on Interfaces
+ if (ReflectedType.IsGenericParameter)
+ {
+ Type[] interfaces = ReflectedType.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, (RuntimeType)interfaces[i], ref list);
+ PopulateRtFields(filter, (RuntimeType)interfaces[i], ref list);
+ }
+ }
+ else
+ {
+ Type[] interfaces = RuntimeTypeHandle.GetInterfaces(ReflectedType);
+
+ 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, (RuntimeType)interfaces[i], ref list);
+ PopulateRtFields(filter, (RuntimeType)interfaces[i], ref list);
+ }
+ }
+ }
+ #endregion
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void PopulateRtFields(Filter filter, RuntimeType declaringType, ref ListBuilder<RuntimeFieldInfo> list)
+ {
+ IntPtr* pResult = stackalloc IntPtr[64];
+ int count = 64;
+
+ if (!RuntimeTypeHandle.GetFields(declaringType, pResult, &count))
+ {
+ fixed(IntPtr* pBigResult = new IntPtr[count])
+ {
+ RuntimeTypeHandle.GetFields(declaringType, pBigResult, &count);
+ PopulateRtFields(filter, pBigResult, count, declaringType, ref list);
+ }
+ }
+ else if (count > 0)
+ {
+ PopulateRtFields(filter, pResult, count, declaringType, ref list);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe void PopulateRtFields(Filter filter,
+ IntPtr* ppFieldHandles, int count, RuntimeType declaringType, ref ListBuilder<RuntimeFieldInfo> list)
+ {
+ Contract.Requires(declaringType != null);
+ Contract.Requires(ReflectedType != null);
+
+ bool needsStaticFieldForGeneric = RuntimeTypeHandle.HasInstantiation(declaringType) && !RuntimeTypeHandle.ContainsGenericVariables(declaringType);
+ bool isInherited = declaringType != ReflectedType;
+
+ for(int i = 0; i < count; i ++)
+ {
+ RuntimeFieldHandleInternal runtimeFieldHandle = new RuntimeFieldHandleInternal(ppFieldHandles[i]);
+
+ if (filter.RequiresStringComparison())
+ {
+ if (!RuntimeFieldHandle.MatchesNameHash(runtimeFieldHandle, filter.GetHashToMatch()))
+ {
+ Contract.Assert(!filter.Match(RuntimeFieldHandle.GetUtf8Name(runtimeFieldHandle)));
+ continue;
+ }
+
+ if (!filter.Match(RuntimeFieldHandle.GetUtf8Name(runtimeFieldHandle)))
+ continue;
+ }
+
+ Contract.Assert(!runtimeFieldHandle.IsNullHandle());
+
+ FieldAttributes fieldAttributes = RuntimeFieldHandle.GetAttributes(runtimeFieldHandle);
+ 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(runtimeFieldHandle, declaringType);
+
+ RuntimeFieldInfo runtimeFieldInfo =
+ new RtFieldInfo(runtimeFieldHandle, declaringType, m_runtimeTypeCache, bindingFlags);
+
+ list.Add(runtimeFieldInfo);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void PopulateLiteralFields(Filter filter, RuntimeType declaringType, ref ListBuilder<RuntimeFieldInfo> list)
+ {
+ Contract.Requires(declaringType != null);
+ Contract.Requires(ReflectedType != null);
+
+ int tkDeclaringType = RuntimeTypeHandle.GetToken(declaringType);
+
+ // Our policy is that TypeDescs do not have metadata tokens
+ if (MdToken.IsNullToken(tkDeclaringType))
+ return;
+
+ MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType);
+
+ MetadataEnumResult tkFields;
+ scope.EnumFields(tkDeclaringType, out tkFields);
+
+ for (int i = 0; i < tkFields.Length; i++)
+ {
+ int tkField = tkFields[i];
+ Contract.Assert(MdToken.IsTokenOfType(tkField, MetadataTokenType.FieldDef));
+ Contract.Assert(!MdToken.IsNullToken(tkField));
+
+ FieldAttributes fieldAttributes;
+ scope.GetFieldDefProps(tkField, out fieldAttributes);
+
+ FieldAttributes fieldAccess = fieldAttributes & FieldAttributes.FieldAccessMask;
+
+ if ((fieldAttributes & FieldAttributes.Literal) != 0)
+ {
+ bool isInherited = declaringType != ReflectedType;
+ if (isInherited)
+ {
+ bool isPrivate = fieldAccess == FieldAttributes.Private;
+ if (isPrivate)
+ continue;
+ }
+
+ if (filter.RequiresStringComparison())
+ {
+ Utf8String name;
+ name = scope.GetName(tkField);
+
+ if (!filter.Match(name))
+ 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, declaringType.GetTypeHandleInternal(), m_runtimeTypeCache, bindingFlags);
+
+ list.Add(runtimeFieldInfo);
+ }
+ }
+ }
+
+ private static void AddElementTypes(Type template, IList<Type> 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 void AddSpecialInterface(ref ListBuilder<RuntimeType> list, Filter filter, RuntimeType iList, bool addSubInterface)
+ {
+ if (iList.IsAssignableFrom(ReflectedType))
+ {
+ if (filter.Match(RuntimeTypeHandle.GetUtf8Name(iList)))
+ list.Add(iList);
+
+ if (addSubInterface)
+ {
+ Type[] iFaces = iList.GetInterfaces();
+ for (int j = 0; j < iFaces.Length; j++)
+ {
+ RuntimeType iFace = (RuntimeType)iFaces[j];
+ if (iFace.IsGenericType && filter.Match(RuntimeTypeHandle.GetUtf8Name(iFace)))
+ list.Add(iFace);
+ }
+ }
+ }
+
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private RuntimeType[] PopulateInterfaces(Filter filter)
+ {
+ ListBuilder<RuntimeType> list = new ListBuilder<RuntimeType>();
+
+ RuntimeType declaringType = ReflectedType;
+
+ if (!RuntimeTypeHandle.IsGenericVariable(declaringType))
+ {
+ Type[] ifaces = RuntimeTypeHandle.GetInterfaces(declaringType);
+
+ if (ifaces != null)
+ {
+ for (int i = 0; i < ifaces.Length; i++)
+ {
+ RuntimeType interfaceType = (RuntimeType)ifaces[i];
+
+ if (filter.RequiresStringComparison())
+ {
+ if (!filter.Match(RuntimeTypeHandle.GetUtf8Name(interfaceType)))
+ continue;
+ }
+
+ Contract.Assert(interfaceType.IsInterface);
+ list.Add(interfaceType);
+ }
+ }
+
+ if (ReflectedType.IsSzArray)
+ {
+ RuntimeType arrayType = (RuntimeType)ReflectedType.GetElementType();
+
+ if (!arrayType.IsPointer)
+ {
+ AddSpecialInterface(ref list, filter, (RuntimeType)typeof(IList<>).MakeGenericType(arrayType), true);
+
+ // To avoid adding a duplicate IEnumerable<T>, we don't add the sub interfaces of IReadOnlyList.
+ // Instead, we add IReadOnlyCollection<T> separately.
+ AddSpecialInterface(ref list, filter, (RuntimeType)typeof(IReadOnlyList<>).MakeGenericType(arrayType), false);
+ AddSpecialInterface(ref list, filter, (RuntimeType)typeof(IReadOnlyCollection<>).MakeGenericType(arrayType), false);
+ }
+ }
+ }
+ else
+ {
+ List<RuntimeType> al = new List<RuntimeType>();
+
+ // Get all constraints
+ Type[] constraints = declaringType.GetGenericParameterConstraints();
+
+ // Populate transitive closure of all interfaces in constraint set
+ for (int i = 0; i < constraints.Length; i++)
+ {
+ RuntimeType constraint = (RuntimeType)constraints[i];
+ if (constraint.IsInterface)
+ al.Add(constraint);
+
+ Type[] temp = constraint.GetInterfaces();
+ for (int j = 0; j < temp.Length; j++)
+ al.Add(temp[j] as RuntimeType);
+ }
+
+ // Remove duplicates
+ Dictionary<RuntimeType, RuntimeType> ht = new Dictionary<RuntimeType, RuntimeType>();
+ for (int i = 0; i < al.Count; i++)
+ {
+ RuntimeType constraint = al[i];
+ if (!ht.ContainsKey(constraint))
+ ht[constraint] = constraint;
+ }
+
+ RuntimeType[] interfaces = new RuntimeType[ht.Values.Count];
+ ht.Values.CopyTo(interfaces, 0);
+
+ // Populate link-list
+ for (int i = 0; i < interfaces.Length; i++)
+ {
+ if (filter.RequiresStringComparison())
+ {
+ if (!filter.Match(RuntimeTypeHandle.GetUtf8Name(interfaces[i])))
+ continue;
+ }
+
+ list.Add(interfaces[i]);
+ }
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe RuntimeType[] PopulateNestedClasses(Filter filter)
+ {
+ RuntimeType declaringType = ReflectedType;
+
+ while (RuntimeTypeHandle.IsGenericVariable(declaringType))
+ {
+ declaringType = declaringType.GetBaseType();
+ }
+
+ int tkEnclosingType = RuntimeTypeHandle.GetToken(declaringType);
+
+ // For example, TypeDescs do not have metadata tokens
+ if (MdToken.IsNullToken(tkEnclosingType))
+ return EmptyArray<RuntimeType>.Value;
+
+ ListBuilder<RuntimeType> list = new ListBuilder<RuntimeType>();
+
+ RuntimeModule moduleHandle = RuntimeTypeHandle.GetModule(declaringType);
+ MetadataImport scope = ModuleHandle.GetMetadataImport(moduleHandle);
+
+ MetadataEnumResult tkNestedClasses;
+ scope.EnumNestedTypes(tkEnclosingType, out tkNestedClasses);
+
+ for (int i = 0; i < tkNestedClasses.Length; i++)
+ {
+ RuntimeType nestedType = null;
+
+ try
+ {
+ nestedType = ModuleHandle.ResolveTypeHandleInternal(moduleHandle, tkNestedClasses[i], null, null);
+ }
+ 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.RequiresStringComparison())
+ {
+ if (!filter.Match(RuntimeTypeHandle.GetUtf8Name(nestedType)))
+ continue;
+ }
+
+ list.Add(nestedType);
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe RuntimeEventInfo[] PopulateEvents(Filter filter)
+ {
+ Contract.Requires(ReflectedType != null);
+
+ // Do not create the dictionary if we are filtering the properties by name already
+ Dictionary<String, RuntimeEventInfo> csEventInfos = filter.CaseSensitive() ? null :
+ new Dictionary<String, RuntimeEventInfo>();
+
+ RuntimeType declaringType = ReflectedType;
+ ListBuilder<RuntimeEventInfo> list = new ListBuilder<RuntimeEventInfo>();
+
+ if (!RuntimeTypeHandle.IsInterface(declaringType))
+ {
+ while(RuntimeTypeHandle.IsGenericVariable(declaringType))
+ declaringType = declaringType.GetBaseType();
+
+ // Populate associates off of the class hierarchy
+ while(declaringType != null)
+ {
+ PopulateEvents(filter, declaringType, csEventInfos, ref list);
+ declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
+ }
+ }
+ else
+ {
+ // Populate associates for this interface
+ PopulateEvents(filter, declaringType, csEventInfos, ref list);
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void PopulateEvents(
+ Filter filter, RuntimeType declaringType, Dictionary<String, RuntimeEventInfo> csEventInfos, ref ListBuilder<RuntimeEventInfo> list)
+ {
+ int tkDeclaringType = RuntimeTypeHandle.GetToken(declaringType);
+
+ // Arrays, Pointers, ByRef types and others generated only the fly by the RT do not have tokens.
+ if (MdToken.IsNullToken(tkDeclaringType))
+ return;
+
+ MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType);
+
+ MetadataEnumResult tkEvents;
+ scope.EnumEvents(tkDeclaringType, out tkEvents);
+
+ for (int i = 0; i < tkEvents.Length; i++)
+ {
+ int tkEvent = tkEvents[i];
+ bool isPrivate;
+
+ Contract.Assert(!MdToken.IsNullToken(tkEvent));
+ Contract.Assert(MdToken.IsTokenOfType(tkEvent, MetadataTokenType.Event));
+
+ if (filter.RequiresStringComparison())
+ {
+ Utf8String name;
+ name = scope.GetName(tkEvent);
+
+ if (!filter.Match(name))
+ continue;
+ }
+
+ RuntimeEventInfo eventInfo = new RuntimeEventInfo(
+ tkEvent, declaringType, m_runtimeTypeCache, out isPrivate);
+
+ #region Remove Inherited Privates
+ if (declaringType != m_runtimeTypeCache.GetRuntimeType() && isPrivate)
+ continue;
+ #endregion
+
+ #region Remove Duplicates
+ if (csEventInfos != null)
+ {
+ string name = eventInfo.Name;
+
+ if (csEventInfos.GetValueOrDefault(name) != null)
+ continue;
+
+ csEventInfos[name] = eventInfo;
+ }
+ else
+ {
+ if (list.Count > 0)
+ break;
+ }
+ #endregion
+
+ list.Add(eventInfo);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe RuntimePropertyInfo[] PopulateProperties(Filter filter)
+ {
+ Contract.Requires(ReflectedType != null);
+
+ // m_csMemberInfos can be null at this point. It will be initialized when Insert
+ // is called in Populate after this returns.
+
+ RuntimeType declaringType = ReflectedType;
+ Contract.Assert(declaringType != null);
+
+ ListBuilder<RuntimePropertyInfo> list = new ListBuilder<RuntimePropertyInfo>();
+
+ if (!RuntimeTypeHandle.IsInterface(declaringType))
+ {
+ while(RuntimeTypeHandle.IsGenericVariable(declaringType))
+ declaringType = declaringType.GetBaseType();
+
+ // Do not create the dictionary if we are filtering the properties by name already
+ Dictionary<String, List<RuntimePropertyInfo>> csPropertyInfos = filter.CaseSensitive() ? null :
+ new Dictionary<String, List<RuntimePropertyInfo>>();
+
+ // All elements automatically initialized to false.
+ bool[] usedSlots = new bool[RuntimeTypeHandle.GetNumVirtuals(declaringType)];
+
+ // Populate associates off of the class hierarchy
+ do
+ {
+ PopulateProperties(filter, declaringType, csPropertyInfos, usedSlots, ref list);
+ declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
+ } while (declaringType != null);
+ }
+ else
+ {
+ // Populate associates for this interface
+ PopulateProperties(filter, declaringType, null, null, ref list);
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void PopulateProperties(
+ Filter filter,
+ RuntimeType declaringType,
+ Dictionary<String, List<RuntimePropertyInfo>> csPropertyInfos,
+ bool[] usedSlots,
+ ref ListBuilder<RuntimePropertyInfo> list)
+ {
+ int tkDeclaringType = RuntimeTypeHandle.GetToken(declaringType);
+
+ // Arrays, Pointers, ByRef types and others generated only the fly by the RT do not have tokens.
+ if (MdToken.IsNullToken(tkDeclaringType))
+ return;
+
+ MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType);
+
+ MetadataEnumResult tkProperties;
+ scope.EnumProperties(tkDeclaringType, out tkProperties);
+
+ RuntimeModule declaringModuleHandle = RuntimeTypeHandle.GetModule(declaringType);
+
+ int numVirtuals = RuntimeTypeHandle.GetNumVirtuals(declaringType);
+
+ Contract.Assert((declaringType.IsInterface && usedSlots == null && csPropertyInfos == null) ||
+ (!declaringType.IsInterface && usedSlots != null && usedSlots.Length >= numVirtuals));
+
+ for (int i = 0; i < tkProperties.Length; i++)
+ {
+ int tkProperty = tkProperties[i];
+ bool isPrivate;
+
+ Contract.Assert(!MdToken.IsNullToken(tkProperty));
+ Contract.Assert(MdToken.IsTokenOfType(tkProperty, MetadataTokenType.Property));
+
+ if (filter.RequiresStringComparison())
+ {
+ if (!ModuleHandle.ContainsPropertyMatchingHash(declaringModuleHandle, tkProperty, filter.GetHashToMatch()))
+ {
+ Contract.Assert(!filter.Match(declaringType.GetRuntimeModule().MetadataImport.GetName(tkProperty)));
+ continue;
+ }
+
+ Utf8String name;
+ name = declaringType.GetRuntimeModule().MetadataImport.GetName(tkProperty);
+
+ if (!filter.Match(name))
+ continue;
+ }
+
+ RuntimePropertyInfo propertyInfo =
+ new RuntimePropertyInfo(
+ tkProperty, declaringType, m_runtimeTypeCache, out isPrivate);
+
+ // If this is a class, not an interface
+ if (usedSlots != null)
+ {
+ #region Remove Privates
+ if (declaringType != ReflectedType && isPrivate)
+ continue;
+ #endregion
+
+ #region Duplicate check based on vtable slots
+
+ // The inheritance of properties are defined by the inheritance of their
+ // getters and setters.
+ // A property on a base type is "overriden" by a property on a sub type
+ // if the getter/setter of the latter occupies the same vtable slot as
+ // the getter/setter of the former.
+
+ MethodInfo associateMethod = propertyInfo.GetGetMethod();
+ if (associateMethod == null)
+ {
+ // We only need to examine the setter if a getter doesn't exist.
+ // It is not logical for the getter to be virtual but not the setter.
+ associateMethod = propertyInfo.GetSetMethod();
+ }
+
+ if (associateMethod != null)
+ {
+ int slot = RuntimeMethodHandle.GetSlot((RuntimeMethodInfo)associateMethod);
+
+ if (slot < numVirtuals)
+ {
+ Contract.Assert(associateMethod.IsVirtual);
+ if (usedSlots[slot] == true)
+ continue;
+ else
+ usedSlots[slot] = true;
+ }
+ }
+ #endregion
+
+ #region Duplicate check based on name and signature
+
+ // For backward compatibility, even if the vtable slots don't match, we will still treat
+ // a property as duplicate if the names and signatures match.
+
+ if (csPropertyInfos != null)
+ {
+ string name = propertyInfo.Name;
+
+ List<RuntimePropertyInfo> cache = csPropertyInfos.GetValueOrDefault(name);
+
+ if (cache == null)
+ {
+ cache = new List<RuntimePropertyInfo>(1);
+ csPropertyInfos[name] = cache;
+ }
+
+ for (int j = 0; j < cache.Count; j++)
+ {
+ if (propertyInfo.EqualsSig(cache[j]))
+ {
+ cache = null;
+ break;
+ }
+ }
+
+ if (cache == null)
+ continue;
+
+ cache.Add(propertyInfo);
+ }
+ else
+ {
+ bool duplicate = false;
+
+ for (int j = 0; j < list.Count; j++)
+ {
+ if (propertyInfo.EqualsSig(list[j]))
+ {
+ duplicate = true;
+ break;
+ }
+ }
+
+ if (duplicate)
+ continue;
+ }
+ #endregion
+ }
+
+ list.Add(propertyInfo);
+ }
+ }
+ #endregion
+
+ #region NonPrivate Members
+ internal T[] GetMemberList(MemberListType listType, string name, CacheType cacheType)
+ {
+ T[] list = null;
+
+ switch(listType)
+ {
+ case MemberListType.CaseSensitive:
+ list = m_csMemberInfos[name];
+ if (list != null)
+ return list;
+
+ return Populate(name, listType, cacheType);
+
+ case MemberListType.CaseInsensitive:
+ list = m_cisMemberInfos[name];
+ if (list != null)
+ return list;
+
+ return Populate(name, listType, cacheType);
+
+ default:
+ Contract.Assert(listType == MemberListType.All);
+ if (Volatile.Read(ref m_cacheComplete))
+ return m_allMembers;
+
+ return Populate(null, listType, cacheType);
+ }
+ }
+
+ internal RuntimeType ReflectedType
+ {
+ get
+ {
+ return m_runtimeTypeCache.GetRuntimeType();
+ }
+ }
+ #endregion
+ }
+ #endregion
+
+ #region Private Data Members
+ private RuntimeType m_runtimeType;
+ private RuntimeType m_enclosingType;
+ private TypeCode m_typeCode;
+ private string m_name;
+ private string m_fullname;
+ private string m_toString;
+ private string m_namespace;
+ private string m_serializationname;
+ private bool m_isGlobal;
+ private bool m_bIsDomainInitialized;
+ private MemberInfoCache<RuntimeMethodInfo> m_methodInfoCache;
+ private MemberInfoCache<RuntimeConstructorInfo> m_constructorInfoCache;
+ private MemberInfoCache<RuntimeFieldInfo> m_fieldInfoCache;
+ private MemberInfoCache<RuntimeType> m_interfaceCache;
+ private MemberInfoCache<RuntimeType> m_nestedClassesCache;
+ private MemberInfoCache<RuntimePropertyInfo> m_propertyInfoCache;
+ private MemberInfoCache<RuntimeEventInfo> m_eventInfoCache;
+ private static CerHashtable<RuntimeMethodInfo, RuntimeMethodInfo> s_methodInstantiations;
+ private static Object s_methodInstantiationsLock;
+#if !FEATURE_CORECLR
+ private RuntimeConstructorInfo m_serializationCtor;
+#endif
+ private string m_defaultMemberName;
+ private Object m_genericCache; // Generic cache for rare scenario specific data. It is used to cache Enum names and values.
+ #endregion
+
+ #region Constructor
+ internal RuntimeTypeCache(RuntimeType runtimeType)
+ {
+ m_typeCode = TypeCode.Empty;
+ m_runtimeType = runtimeType;
+ m_isGlobal = RuntimeTypeHandle.GetModule(runtimeType).RuntimeType == runtimeType;
+ }
+ #endregion
+
+ #region Private Members
+ private string ConstructName(ref string name, TypeNameFormatFlags formatFlags)
+ {
+ if (name == null)
+ {
+ name = new RuntimeTypeHandle(m_runtimeType).ConstructName(formatFlags);
+ }
+ return name;
+ }
+
+ private T[] GetMemberList<T>(ref MemberInfoCache<T> m_cache, MemberListType listType, string name, CacheType cacheType)
+ where T : MemberInfo
+ {
+ MemberInfoCache<T> existingCache = GetMemberCache<T>(ref m_cache);
+ return existingCache.GetMemberList(listType, name, cacheType);
+ }
+
+ private MemberInfoCache<T> GetMemberCache<T>(ref MemberInfoCache<T> m_cache)
+ where T : MemberInfo
+ {
+ MemberInfoCache<T> existingCache = m_cache;
+
+ if (existingCache == null)
+ {
+ MemberInfoCache<T> newCache = new MemberInfoCache<T>(this);
+ existingCache = Interlocked.CompareExchange(ref m_cache, newCache, null);
+ if (existingCache == null)
+ existingCache = newCache;
+ }
+
+ return existingCache;
+ }
+ #endregion
+
+ #region Internal Members
+
+ internal Object GenericCache
+ {
+ get { return m_genericCache; }
+ set { m_genericCache = value; }
+ }
+
+ internal bool DomainInitialized
+ {
+ get { return m_bIsDomainInitialized; }
+ set { m_bIsDomainInitialized = value; }
+ }
+
+ internal string GetName(TypeNameKind kind)
+ {
+ switch (kind)
+ {
+ case TypeNameKind.Name:
+ // No namespace, full instantiation, and assembly.
+ return ConstructName(ref m_name, TypeNameFormatFlags.FormatBasic);
+
+ case TypeNameKind.FullName:
+ // We exclude the types that contain generic parameters because their names cannot be roundtripped.
+ // We allow generic type definitions (and their refs, ptrs, and arrays) because their names can be roundtriped.
+ // Theoretically generic types instantiated with generic type definitions can be roundtripped, e.g. List`1<Dictionary`2>.
+ // But these kind of types are useless, rare, and hard to identity. We would need to recursively examine all the
+ // generic arguments with the same criteria. We will exclude them unless we see a real user scenario.
+ if (!m_runtimeType.GetRootElementType().IsGenericTypeDefinition && m_runtimeType.ContainsGenericParameters)
+ return null;
+
+ // No assembly.
+ return ConstructName(ref m_fullname, TypeNameFormatFlags.FormatNamespace | TypeNameFormatFlags.FormatFullInst);
+
+ case TypeNameKind.ToString:
+ // No full instantiation and assembly.
+ return ConstructName(ref m_toString, TypeNameFormatFlags.FormatNamespace);
+
+ case TypeNameKind.SerializationName:
+ // Use FormatGenericParam in serialization. Otherwise we won't be able
+ // to distinguish between a generic parameter and a normal type with the same name.
+ // e.g. Foo<T>.Bar(T t), the parameter type T could be !1 or a real type named "T".
+ // Excluding the version number in the assembly name for VTS.
+ return ConstructName(ref m_serializationname, TypeNameFormatFlags.FormatSerialization);
+
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ 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 = RuntimeTypeHandle.GetMetadataImport((RuntimeType)type).GetNamespace(type.MetadataToken).ToString();
+ }
+
+ return m_namespace;
+ }
+
+ internal TypeCode TypeCode
+ {
+ get { return m_typeCode; }
+ set { m_typeCode = value; }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe RuntimeType GetEnclosingType()
+ {
+ if (m_enclosingType == null)
+ {
+ // Use void as a marker of null enclosing type
+ RuntimeType enclosingType = RuntimeTypeHandle.GetDeclaringType(GetRuntimeType());
+ Contract.Assert(enclosingType != typeof(void));
+ m_enclosingType = enclosingType ?? (RuntimeType)typeof(void);
+ }
+
+ return (m_enclosingType == typeof(void)) ? null : m_enclosingType;
+ }
+
+ internal RuntimeType GetRuntimeType()
+ {
+ return m_runtimeType;
+ }
+
+ internal bool IsGlobal
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get { return m_isGlobal; }
+ }
+
+ internal void InvalidateCachedNestedType()
+ {
+ m_nestedClassesCache = null;
+ }
+
+#if !FEATURE_CORECLR
+ internal RuntimeConstructorInfo GetSerializationCtor()
+ {
+ if (m_serializationCtor == null)
+ {
+ if (s_SICtorParamTypes == null)
+ s_SICtorParamTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
+
+ m_serializationCtor = m_runtimeType.GetConstructor(
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ CallingConventions.Any,
+ s_SICtorParamTypes,
+ null) as RuntimeConstructorInfo;
+ }
+
+ return m_serializationCtor;
+ }
+#endif //!FEATURE_CORECLR
+
+ internal string GetDefaultMemberName()
+ {
+ if (m_defaultMemberName == null)
+ {
+ CustomAttributeData attr = null;
+ Type DefaultMemberAttrType = typeof(DefaultMemberAttribute);
+ for (RuntimeType t = m_runtimeType; t != null; t = t.GetBaseType())
+ {
+ IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes(t);
+ for (int i = 0; i < attrs.Count; i++)
+ {
+ if (Object.ReferenceEquals(attrs[i].Constructor.DeclaringType, DefaultMemberAttrType))
+ {
+ attr = attrs[i];
+ break;
+ }
+ }
+
+ if (attr != null)
+ {
+ m_defaultMemberName = attr.ConstructorArguments[0].Value as string;
+ break;
+ }
+ }
+ }
+
+ return m_defaultMemberName;
+ }
+ #endregion
+
+ #region Caches Accessors
+ [System.Security.SecurityCritical] // auto-generated
+ internal MethodInfo GetGenericMethodInfo(RuntimeMethodHandleInternal genericMethod)
+ {
+ LoaderAllocator la = RuntimeMethodHandle.GetLoaderAllocator(genericMethod);
+
+ RuntimeMethodInfo rmi = new RuntimeMethodInfo(
+ genericMethod, RuntimeMethodHandle.GetDeclaringType(genericMethod), this,
+ RuntimeMethodHandle.GetAttributes(genericMethod), (BindingFlags)(-1), la);
+
+ RuntimeMethodInfo crmi;
+ if (la != null)
+ {
+ crmi = la.m_methodInstantiations[rmi];
+ }
+ else
+ {
+ crmi = s_methodInstantiations[rmi];
+ }
+ if (crmi != null)
+ return crmi;
+
+ if (s_methodInstantiationsLock == null)
+ Interlocked.CompareExchange(ref s_methodInstantiationsLock, new Object(), null);
+
+ bool lockTaken = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(s_methodInstantiationsLock, ref lockTaken);
+
+ if (la != null)
+ {
+ crmi = la.m_methodInstantiations[rmi];
+ if (crmi != null)
+ return crmi;
+ la.m_methodInstantiations[rmi] = rmi;
+ }
+ else
+ {
+ crmi = s_methodInstantiations[rmi];
+ if (crmi != null)
+ return crmi;
+ s_methodInstantiations[rmi] = rmi;
+ }
+ }
+ finally
+ {
+ if (lockTaken)
+ {
+ Monitor.Exit(s_methodInstantiationsLock);
+ }
+ }
+
+ return rmi;
+ }
+
+ internal RuntimeMethodInfo[] GetMethodList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeMethodInfo>(ref m_methodInfoCache, listType, name, CacheType.Method);
+ }
+
+ internal RuntimeConstructorInfo[] GetConstructorList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeConstructorInfo>(ref m_constructorInfoCache, listType, name, CacheType.Constructor);
+ }
+
+ internal RuntimePropertyInfo[] GetPropertyList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimePropertyInfo>(ref m_propertyInfoCache, listType, name, CacheType.Property);
+ }
+
+ internal RuntimeEventInfo[] GetEventList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeEventInfo>(ref m_eventInfoCache, listType, name, CacheType.Event);
+ }
+
+ internal RuntimeFieldInfo[] GetFieldList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeFieldInfo>(ref m_fieldInfoCache, listType, name, CacheType.Field);
+ }
+
+ internal RuntimeType[] GetInterfaceList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeType>(ref m_interfaceCache, listType, name, CacheType.Interface);
+ }
+
+ internal RuntimeType[] GetNestedTypeList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeType>(ref m_nestedClassesCache, listType, name, CacheType.NestedType);
+ }
+
+ internal MethodBase GetMethod(RuntimeType declaringType, RuntimeMethodHandleInternal method)
+ {
+ GetMemberCache<RuntimeMethodInfo>(ref m_methodInfoCache);
+ return m_methodInfoCache.AddMethod(declaringType, method, CacheType.Method);
+ }
+
+ internal MethodBase GetConstructor(RuntimeType declaringType, RuntimeMethodHandleInternal constructor)
+ {
+ GetMemberCache<RuntimeConstructorInfo>(ref m_constructorInfoCache);
+ return m_constructorInfoCache.AddMethod(declaringType, constructor, CacheType.Constructor);
+ }
+
+ internal FieldInfo GetField(RuntimeFieldHandleInternal field)
+ {
+ GetMemberCache<RuntimeFieldInfo>(ref m_fieldInfoCache);
+ return m_fieldInfoCache.AddField(field);
+ }
+
+ #endregion
+ }
+ #endregion
+
+#if FEATURE_REMOTING
+ #region Legacy Remoting Cache
+ // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h.
+ // This member is currently being used by Remoting for caching remoting data. If you
+ // need to cache data here, talk to the Remoting team to work out a mechanism, so that
+ // both caching systems can happily work together.
+ private RemotingTypeCachedData m_cachedData;
+
+ internal RemotingTypeCachedData RemotingCache
+ {
+ get
+ {
+ // This grabs an internal copy of m_cachedData and uses
+ // that instead of looking at m_cachedData directly because
+ // the cache may get cleared asynchronously. This prevents
+ // us from having to take a lock.
+ RemotingTypeCachedData cache = m_cachedData;
+ if (cache == null)
+ {
+ cache = new RemotingTypeCachedData(this);
+ RemotingTypeCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
+ if (ret != null)
+ cache = ret;
+ }
+ return cache;
+ }
+ }
+ #endregion
+#endif //FEATURE_REMOTING
+
+ #region Static Members
+
+ #region Internal
+ internal static RuntimeType GetType(String typeName, bool throwOnError, bool ignoreCase, bool reflectionOnly,
+ ref StackCrawlMark stackMark)
+ {
+ if (typeName == null)
+ throw new ArgumentNullException("typeName");
+ Contract.EndContractBlock();
+
+ return RuntimeTypeHandle.GetTypeByName(
+ typeName, throwOnError, ignoreCase, reflectionOnly, ref stackMark, false);
+ }
+
+ internal static MethodBase GetMethodBase(RuntimeModule scope, int typeMetadataToken)
+ {
+ return GetMethodBase(ModuleHandle.ResolveMethodHandleInternal(scope, typeMetadataToken));
+ }
+
+ internal static MethodBase GetMethodBase(IRuntimeMethodInfo methodHandle)
+ {
+ return GetMethodBase(null, methodHandle);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal static MethodBase GetMethodBase(RuntimeType reflectedType, IRuntimeMethodInfo methodHandle)
+ {
+ MethodBase retval = RuntimeType.GetMethodBase(reflectedType, methodHandle.Value);
+ GC.KeepAlive(methodHandle);
+ return retval;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static MethodBase GetMethodBase(RuntimeType reflectedType, RuntimeMethodHandleInternal methodHandle)
+ {
+ Contract.Assert(!methodHandle.IsNullHandle());
+
+ if (RuntimeMethodHandle.IsDynamicMethod(methodHandle))
+ {
+ Resolver resolver = RuntimeMethodHandle.GetResolver(methodHandle);
+
+ if (resolver != null)
+ return resolver.GetDynamicMethod();
+
+ return null;
+ }
+
+ // verify the type/method relationship
+ RuntimeType declaredType = RuntimeMethodHandle.GetDeclaringType(methodHandle);
+
+ RuntimeType[] methodInstantiation = null;
+
+ if (reflectedType == null)
+ reflectedType = declaredType as RuntimeType;
+
+ if (reflectedType != declaredType && !reflectedType.IsSubclassOf(declaredType))
+ {
+ // object[] is assignable from string[].
+ if (reflectedType.IsArray)
+ {
+ // The whole purpose of this chunk of code is not only for error checking.
+ // GetMember has a side effect of populating the member cache of reflectedType,
+ // doing so will ensure we construct the correct MethodInfo/ConstructorInfo objects.
+ // Without this the reflectedType.Cache.GetMethod call below may return a MethodInfo
+ // object whose ReflectedType is string[] and DeclaringType is object[]. That would
+ // be (arguabally) incorrect because string[] is not a subclass of object[].
+ MethodBase[] methodBases = reflectedType.GetMember(
+ RuntimeMethodHandle.GetName(methodHandle), MemberTypes.Constructor | MemberTypes.Method,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) as MethodBase[];
+
+ bool loaderAssuredCompatible = false;
+ for (int i = 0; i < methodBases.Length; i++)
+ {
+ IRuntimeMethodInfo rmi = (IRuntimeMethodInfo)methodBases[i];
+ if (rmi.Value.Value == methodHandle.Value)
+ loaderAssuredCompatible = true;
+ }
+
+ if (!loaderAssuredCompatible)
+ throw new ArgumentException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveMethodHandle"),
+ reflectedType.ToString(), declaredType.ToString()));
+ }
+ // Action<in string> is assignable from, but not a subclass of Action<in object>.
+ else if (declaredType.IsGenericType)
+ {
+ // ignoring instantiation is the ReflectedType a subtype of the DeclaringType
+ RuntimeType declaringDefinition = (RuntimeType)declaredType.GetGenericTypeDefinition();
+
+ RuntimeType baseType = reflectedType;
+
+ while (baseType != null)
+ {
+ RuntimeType baseDefinition = baseType;
+
+ if (baseDefinition.IsGenericType && !baseType.IsGenericTypeDefinition)
+ baseDefinition = (RuntimeType)baseDefinition.GetGenericTypeDefinition();
+
+ if (baseDefinition == declaringDefinition)
+ break;
+
+ baseType = baseType.GetBaseType();
+ }
+
+ 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;
+
+ // 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 (!RuntimeMethodHandle.IsGenericMethodDefinition(methodHandle))
+ {
+ methodInstantiation = RuntimeMethodHandle.GetMethodInstantiationInternal(methodHandle);
+ }
+
+ // lookup via v-table slot the RuntimeMethodHandle on the new declaring type
+ methodHandle = RuntimeMethodHandle.GetMethodFromCanonical(methodHandle, declaredType);
+ }
+ else if (!declaredType.IsAssignableFrom(reflectedType))
+ {
+ // declaredType is not Array, not generic, and not assignable from reflectedType
+ throw new ArgumentException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveMethodHandle"),
+ reflectedType.ToString(), declaredType.ToString()));
+ }
+ }
+
+ // If methodInstantiation is not null, GetStubIfNeeded will rebind the generic method arguments
+ // if declaredType is an instantiated generic type and methodHandle is not generic, get the instantiated MethodDesc (if needed)
+ // if declaredType is a value type, get the unboxing stub (if needed)
+
+ // this is so that our behavior here is consistent with that of Type.GetMethod
+ // See MemberInfoCache<RuntimeConstructorInfo>.PopulateMethods and MemberInfoCache<RuntimeMethodInfoInfo>.PopulateConstructors
+
+ methodHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaredType, methodInstantiation);
+ MethodBase retval;
+
+ if (RuntimeMethodHandle.IsConstructor(methodHandle))
+ {
+ // Constructor case: constructors cannot be generic
+ retval = reflectedType.Cache.GetConstructor(declaredType, methodHandle);
+ }
+ else
+ {
+ // Method case
+ if (RuntimeMethodHandle.HasMethodInstantiation(methodHandle) && !RuntimeMethodHandle.IsGenericMethodDefinition(methodHandle))
+ retval = reflectedType.Cache.GetGenericMethodInfo(methodHandle);
+ else
+ retval = reflectedType.Cache.GetMethod(declaredType, methodHandle);
+ }
+
+ GC.KeepAlive(methodInstantiation);
+ return retval;
+ }
+
+ internal Object GenericCache
+ {
+ get { return Cache.GenericCache; }
+ set { Cache.GenericCache = value; }
+ }
+
+ internal bool DomainInitialized
+ {
+ get { return Cache.DomainInitialized; }
+ set { Cache.DomainInitialized = value; }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static FieldInfo GetFieldInfo(IRuntimeFieldInfo fieldHandle)
+ {
+ return GetFieldInfo(RuntimeFieldHandle.GetApproxDeclaringType(fieldHandle), fieldHandle);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static FieldInfo GetFieldInfo(RuntimeType reflectedType, IRuntimeFieldInfo field)
+ {
+ RuntimeFieldHandleInternal fieldHandle = field.Value;
+
+ // verify the type/method relationship
+ if (reflectedType == null)
+ {
+ reflectedType = RuntimeFieldHandle.GetApproxDeclaringType(fieldHandle);
+ }
+ else
+ {
+ RuntimeType declaredType = RuntimeFieldHandle.GetApproxDeclaringType(fieldHandle);
+ if (reflectedType != declaredType)
+ {
+ if (!RuntimeFieldHandle.AcquiresContextFromThis(fieldHandle) ||
+ !RuntimeTypeHandle.CompareCanonicalHandles(declaredType, reflectedType))
+ {
+ throw new ArgumentException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveFieldHandle"),
+ reflectedType.ToString(),
+ declaredType.ToString()));
+ }
+ }
+ }
+
+ FieldInfo retVal = reflectedType.Cache.GetField(fieldHandle);
+ GC.KeepAlive(field);
+ return retVal;
+ }
+
+ // Called internally
+ private unsafe static PropertyInfo GetPropertyInfo(RuntimeType reflectedType, int tkProperty)
+ {
+ RuntimePropertyInfo property = null;
+ RuntimePropertyInfo[] candidates =
+ reflectedType.Cache.GetPropertyList(MemberListType.All, null);
+
+ for (int i = 0; i < candidates.Length; i++)
+ {
+ property = candidates[i];
+ if (property.MetadataToken == tkProperty)
+ return property;
+ }
+
+ Contract.Assume(false, "Unreachable code");
+ throw new SystemException();
+ }
+
+ private static void ThrowIfTypeNeverValidGenericArgument(RuntimeType type)
+ {
+ if (type.IsPointer || type.IsByRef || type == typeof(void))
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_NeverValidGenericArgument", type.ToString()));
+ }
+
+
+ internal static void SanityCheckGenericArguments(RuntimeType[] genericArguments, RuntimeType[] genericParamters)
+ {
+ if (genericArguments == null)
+ throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ 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(
+ Environment.GetResourceString("Argument_NotEnoughGenArguments", genericArguments.Length, genericParamters.Length));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static void ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
+ {
+ RuntimeType[] typeContext = null;
+ RuntimeType[] methodContext = null;
+ RuntimeType[] genericParamters = null;
+
+ if (definition is Type)
+ {
+ RuntimeType genericTypeDefinition = (RuntimeType)definition;
+ genericParamters = genericTypeDefinition.GetGenericArgumentsInternal();
+ typeContext = genericArguments;
+ }
+ else
+ {
+ RuntimeMethodInfo genericMethodDefinition = (RuntimeMethodInfo)definition;
+ genericParamters = genericMethodDefinition.GetGenericArgumentsInternal();
+ methodContext = genericArguments;
+
+ RuntimeType declaringType = (RuntimeType)genericMethodDefinition.DeclaringType;
+ if (declaringType != null)
+ {
+ typeContext = declaringType.GetTypeHandleInternal().GetInstantiationInternal();
+ }
+ }
+
+ for (int i = 0; i < genericArguments.Length; i++)
+ {
+ Type genericArgument = genericArguments[i];
+ Type genericParameter = genericParamters[i];
+
+ if (!RuntimeTypeHandle.SatisfiesConstraints(genericParameter.GetTypeHandleInternal().GetTypeChecked(),
+ typeContext, methodContext, genericArgument.GetTypeHandleInternal().GetTypeChecked()))
+ {
+ throw new ArgumentException(
+ 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 = "";
+ Contract.Assert(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;
+ }
+
+ // Calculate prefixLookup, ignoreCase, and listType for use by GetXXXCandidates
+ 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))
+ {
+ // We set prefixLookup to true if name ends with a "*".
+ // We will also set listType to All so that all members are included in
+ // the candidates which are later filtered by FilterApplyPrefixLookup.
+ name = name.Substring(0, name.Length - 1);
+ prefixLookup = true;
+ listType = MemberListType.All;
+ }
+ }
+ else
+ {
+ listType = MemberListType.All;
+ }
+ }
+
+ // Used by the singular GetXXX APIs (Event, Field, Interface, NestedType) where prefixLookup is not supported.
+ 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);
+ }
+
+ // Only called by GetXXXCandidates, GetInterfaces, and GetNestedTypes when FilterHelper has set "prefixLookup" to true.
+ // Most of the plural GetXXX methods allow prefix lookups while the singular GetXXX methods mostly do not.
+ private static bool FilterApplyPrefixLookup(MemberInfo memberInfo, string name, bool ignoreCase)
+ {
+ Contract.Assert(name != null);
+
+ if (ignoreCase)
+ {
+ if (!memberInfo.Name.StartsWith(name, StringComparison.OrdinalIgnoreCase))
+ return false;
+ }
+ else
+ {
+ if (!memberInfo.Name.StartsWith(name, StringComparison.Ordinal))
+ return false;
+ }
+
+ return true;
+ }
+
+
+ // Used by FilterApplyType to perform all the filtering based on name and BindingFlags
+ private static bool FilterApplyBase(
+ MemberInfo memberInfo, BindingFlags bindingFlags, bool isPublic, bool isNonProtectedInternal, bool isStatic,
+ string name, bool prefixLookup)
+ {
+ #region Preconditions
+ Contract.Requires(memberInfo != null);
+ Contract.Requires(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 = !Object.ReferenceEquals(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;
+ }
+
+
+ // Used by GetInterface and GetNestedType(s) which don't need parameter type filtering.
+ private static bool FilterApplyType(
+ Type type, BindingFlags bindingFlags, string name, bool prefixLookup, string ns)
+ {
+ Contract.Requires((object)type != null);
+ Contract.Assert(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 FilterApplyMethodInfo(
+ RuntimeMethodInfo method, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes)
+ {
+ // Optimization: Pre-Calculate the method binding flags to avoid casting.
+ return FilterApplyMethodBase(method, method.BindingFlags, bindingFlags, callConv, argumentTypes);
+ }
+
+ private static bool FilterApplyConstructorInfo(
+ RuntimeConstructorInfo constructor, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes)
+ {
+ // Optimization: Pre-Calculate the method binding flags to avoid casting.
+ return FilterApplyMethodBase(constructor, constructor.BindingFlags, bindingFlags, callConv, argumentTypes);
+ }
+
+ // Used by GetMethodCandidates/GetConstructorCandidates, InvokeMember, and CreateInstanceImpl to perform the necessary filtering.
+ // Should only be called by FilterApplyMethodInfo and FilterApplyConstructorInfo.
+ private static bool FilterApplyMethodBase(
+ MethodBase methodBase, BindingFlags methodFlags, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes)
+ {
+ Contract.Requires(methodBase != null);
+
+ bindingFlags ^= BindingFlags.DeclaredOnly;
+
+ #region Apply Base Filter
+ if ((bindingFlags & methodFlags) != methodFlags)
+ return false;
+ #endregion
+
+ #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 check.
+ Contract.Assert((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 ((object)argumentTypes[i] != null && !Object.ReferenceEquals(parameterInfos[i].ParameterType, argumentTypes[i]))
+ return false;
+ }
+ }
+ }
+ #endregion
+ }
+ }
+ #endregion
+
+ return true;
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Private Data Members
+ private object m_keepalive; // This will be filled with a LoaderAllocator reference when this RuntimeType represents a collectible type
+ private IntPtr m_cache;
+ internal IntPtr m_handle;
+
+#if FEATURE_APPX
+ private INVOCATION_FLAGS m_invocationFlags;
+
+ internal bool IsNonW8PFrameworkAPI()
+ {
+ if (IsGenericParameter)
+ return false;
+
+ if (HasElementType)
+ return ((RuntimeType)GetElementType()).IsNonW8PFrameworkAPI();
+
+ if (IsSimpleTypeNonW8PFrameworkAPI())
+ return true;
+
+ if (IsGenericType && !IsGenericTypeDefinition)
+ {
+ foreach (Type t in GetGenericArguments())
+ {
+ if (((RuntimeType)t).IsNonW8PFrameworkAPI())
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private bool IsSimpleTypeNonW8PFrameworkAPI()
+ {
+ RuntimeAssembly rtAssembly = GetRuntimeAssembly();
+ if (rtAssembly.IsFrameworkAssembly())
+ {
+ int ctorToken = rtAssembly.InvocableAttributeCtorToken;
+ if (System.Reflection.MetadataToken.IsNullToken(ctorToken) ||
+ !CustomAttribute.IsAttributeDefined(GetRuntimeModule(), MetadataToken, ctorToken))
+ return true;
+ }
+
+ return false;
+ }
+
+ internal INVOCATION_FLAGS InvocationFlags
+ {
+ get
+ {
+ if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
+ {
+ INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN;
+
+ if (AppDomain.ProfileAPICheck && IsNonW8PFrameworkAPI())
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API;
+
+ m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
+ }
+
+ return m_invocationFlags;
+ }
+ }
+#endif // FEATURE_APPX
+
+ internal static readonly RuntimeType ValueType = (RuntimeType)typeof(System.ValueType);
+ internal static readonly RuntimeType EnumType = (RuntimeType)typeof(System.Enum);
+
+ private static readonly RuntimeType ObjectType = (RuntimeType)typeof(System.Object);
+ private static readonly RuntimeType StringType = (RuntimeType)typeof(System.String);
+ private static readonly RuntimeType DelegateType = (RuntimeType)typeof(System.Delegate);
+
+ private static Type[] s_SICtorParamTypes;
+ #endregion
+
+ #region Constructor
+ internal RuntimeType() { throw new NotSupportedException(); }
+ #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 RuntimeTypeCache Cache
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_cache.IsNull())
+ {
+ IntPtr newgcHandle = new RuntimeTypeHandle(this).GetGCHandle(GCHandleType.WeakTrackResurrection);
+ IntPtr gcHandle = Interlocked.CompareExchange(ref m_cache, newgcHandle, (IntPtr)0);
+ // Leak the handle if the type is collectible. It will be reclaimed when
+ // the type goes away.
+ if (!gcHandle.IsNull() && !IsCollectible())
+ GCHandle.InternalFree(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;
+ }
+
+ Contract.Assert(cache != null);
+ return cache;
+ }
+ }
+
+ internal bool IsSpecialSerializableType()
+ {
+ RuntimeType rt = this;
+ do
+ {
+ // In all sane cases we only need to compare the direct level base type with
+ // System.Enum and System.MulticastDelegate. However, a generic argument can
+ // have a base type constraint that is Delegate or even a real delegate type.
+ // Let's maintain compatibility and return true for them.
+ if (rt == RuntimeType.DelegateType || rt == RuntimeType.EnumType)
+ return true;
+
+ rt = rt.GetBaseType();
+ } while (rt != null);
+
+ return false;
+ }
+
+ private string GetDefaultMemberName()
+ {
+ return Cache.GetDefaultMemberName();
+ }
+
+#if !FEATURE_CORECLR
+ internal RuntimeConstructorInfo GetSerializationCtor()
+ {
+ return Cache.GetSerializationCtor();
+ }
+#endif
+ #endregion
+
+ #region Type Overrides
+
+ #region Get XXXInfo Candidates
+ private ListBuilder<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);
+
+ RuntimeMethodInfo[] cache = Cache.GetMethodList(listType, name);
+
+ ListBuilder<MethodInfo> candidates = new ListBuilder<MethodInfo>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeMethodInfo methodInfo = cache[i];
+ if (FilterApplyMethodInfo(methodInfo, bindingAttr, callConv, types) &&
+ (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(methodInfo, name, ignoreCase)))
+ {
+ candidates.Add(methodInfo);
+ }
+ }
+
+ return candidates;
+ }
+
+ private ListBuilder<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);
+
+ RuntimeConstructorInfo[] cache = Cache.GetConstructorList(listType, name);
+
+ ListBuilder<ConstructorInfo> candidates = new ListBuilder<ConstructorInfo>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeConstructorInfo constructorInfo = cache[i];
+ if (FilterApplyConstructorInfo(constructorInfo, bindingAttr, callConv, types) &&
+ (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(constructorInfo, name, ignoreCase)))
+ {
+ candidates.Add(constructorInfo);
+ }
+ }
+
+ return candidates;
+ }
+
+
+ private ListBuilder<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);
+
+ RuntimePropertyInfo[] cache = Cache.GetPropertyList(listType, name);
+
+ bindingAttr ^= BindingFlags.DeclaredOnly;
+
+ ListBuilder<PropertyInfo> candidates = new ListBuilder<PropertyInfo>(cache.Length);
+ for (int i = 0; i < cache.Length; 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;
+ }
+
+ private ListBuilder<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);
+
+ RuntimeEventInfo[] cache = Cache.GetEventList(listType, name);
+
+ bindingAttr ^= BindingFlags.DeclaredOnly;
+
+ ListBuilder<EventInfo> candidates = new ListBuilder<EventInfo>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeEventInfo eventInfo = cache[i];
+ if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags &&
+ (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(eventInfo, name, ignoreCase)))
+ {
+ candidates.Add(eventInfo);
+ }
+ }
+
+ return candidates;
+ }
+
+ private ListBuilder<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);
+
+ RuntimeFieldInfo[] cache = Cache.GetFieldList(listType, name);
+
+ bindingAttr ^= BindingFlags.DeclaredOnly;
+
+ ListBuilder<FieldInfo> candidates = new ListBuilder<FieldInfo>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeFieldInfo fieldInfo = cache[i];
+ if ((bindingAttr & fieldInfo.BindingFlags) == fieldInfo.BindingFlags &&
+ (!prefixLookup || FilterApplyPrefixLookup(fieldInfo, name, ignoreCase)))
+ {
+ candidates.Add(fieldInfo);
+ }
+ }
+
+ return candidates;
+ }
+
+ private ListBuilder<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);
+
+ RuntimeType[] cache = Cache.GetNestedTypeList(listType, name);
+
+ ListBuilder<Type> candidates = new ListBuilder<Type>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeType nestedClass = cache[i];
+ if (RuntimeType.FilterApplyType(nestedClass, bindingAttr, name, prefixLookup, ns))
+ {
+ candidates.Add(nestedClass);
+ }
+ }
+
+ return candidates;
+ }
+ #endregion
+
+ #region Get All XXXInfos
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
+ {
+ return GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, false).ToArray();
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+ {
+ return GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false).ToArray();
+ }
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+ {
+ return GetPropertyCandidates(null, bindingAttr, null, false).ToArray();
+ }
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr)
+ {
+ return GetEventCandidates(null, bindingAttr, false).ToArray();
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr)
+ {
+ return GetFieldCandidates(null, bindingAttr, false).ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type[] GetInterfaces()
+ {
+ RuntimeType[] candidates = this.Cache.GetInterfaceList(MemberListType.All, null);
+ Type[] interfaces = new Type[candidates.Length];
+ for (int i = 0; i < candidates.Length; i++)
+ JitHelpers.UnsafeSetArrayElement(interfaces, i, candidates[i]);
+
+ return interfaces;
+ }
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr)
+ {
+ return GetNestedTypeCandidates(null, bindingAttr, false).ToArray();
+ }
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
+ {
+ ListBuilder<MethodInfo> methods = GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, false);
+ ListBuilder<ConstructorInfo> constructors = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false);
+ ListBuilder<PropertyInfo> properties = GetPropertyCandidates(null, bindingAttr, null, false);
+ ListBuilder<EventInfo> events = GetEventCandidates(null, bindingAttr, false);
+ ListBuilder<FieldInfo> fields = GetFieldCandidates(null, bindingAttr, false);
+ ListBuilder<Type> nestedTypes = GetNestedTypeCandidates(null, bindingAttr, false);
+ // Interfaces are excluded from the result of GetMembers
+
+ MemberInfo[] members = new MemberInfo[
+ methods.Count +
+ constructors.Count +
+ properties.Count +
+ events.Count +
+ fields.Count +
+ nestedTypes.Count];
+
+ int i = 0;
+ methods.CopyTo(members, i); i += methods.Count;
+ constructors.CopyTo(members, i); i += constructors.Count;
+ properties.CopyTo(members, i); i += properties.Count;
+ events.CopyTo(members, i); i += events.Count;
+ fields.CopyTo(members, i); i += fields.Count;
+ nestedTypes.CopyTo(members, i); i += nestedTypes.Count;
+ Contract.Assert(i == members.Length);
+
+ return members;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override InterfaceMapping GetInterfaceMap(Type ifaceType)
+ {
+ if (IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
+
+ if ((object)ifaceType == null)
+ throw new ArgumentNullException("ifaceType");
+ Contract.EndContractBlock();
+
+ RuntimeType ifaceRtType = ifaceType as RuntimeType;
+
+ if (ifaceRtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType");
+
+ RuntimeTypeHandle ifaceRtTypeHandle = ifaceRtType.GetTypeHandleInternal();
+
+ GetTypeHandleInternal().VerifyInterfaceIsImplemented(ifaceRtTypeHandle);
+ Contract.Assert(ifaceType.IsInterface); // VerifyInterfaceIsImplemented enforces this invariant
+ Contract.Assert(!IsInterface); // VerifyInterfaceIsImplemented enforces this invariant
+
+ // SZArrays implement the methods on IList`1, IEnumerable`1, and ICollection`1 with
+ // SZArrayHelper and some runtime magic. We don't have accurate interface maps for them.
+ if (IsSzArray && ifaceType.IsGenericType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ArrayGetInterfaceMap"));
+
+ int ifaceInstanceMethodCount = RuntimeTypeHandle.GetNumVirtuals(ifaceRtType);
+
+ InterfaceMapping im;
+ im.InterfaceType = ifaceType;
+ im.TargetType = this;
+ im.InterfaceMethods = new MethodInfo[ifaceInstanceMethodCount];
+ im.TargetMethods = new MethodInfo[ifaceInstanceMethodCount];
+
+ for (int i = 0; i < ifaceInstanceMethodCount; i++)
+ {
+ RuntimeMethodHandleInternal ifaceRtMethodHandle = RuntimeTypeHandle.GetMethodAt(ifaceRtType, i);
+
+ // GetMethodBase will convert this to the instantiating/unboxing stub if necessary
+ MethodBase ifaceMethodBase = RuntimeType.GetMethodBase(ifaceRtType, ifaceRtMethodHandle);
+ Contract.Assert(ifaceMethodBase is RuntimeMethodInfo);
+ im.InterfaceMethods[i] = (MethodInfo)ifaceMethodBase;
+
+ // If the slot is -1, then virtual stub dispatch is active.
+ int slot = GetTypeHandleInternal().GetInterfaceMethodImplementationSlot(ifaceRtTypeHandle, ifaceRtMethodHandle);
+
+ if (slot == -1) continue;
+
+ RuntimeMethodHandleInternal classRtMethodHandle = RuntimeTypeHandle.GetMethodAt(this, slot);
+
+ // GetMethodBase will convert this to the instantiating/unboxing stub if necessary
+ MethodBase rtTypeMethodBase = RuntimeType.GetMethodBase(this, classRtMethodHandle);
+ // a class may not implement all the methods of an interface (abstract class) so null is a valid value
+ Contract.Assert(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)
+ {
+ ListBuilder<MethodInfo> candidates = GetMethodCandidates(name, bindingAttr, callConv, types, false);
+
+ if (candidates.Count == 0)
+ return null;
+
+ if (types == null || types.Length == 0)
+ {
+ MethodInfo firstCandidate = candidates[0];
+
+ if (candidates.Count == 1)
+ {
+ return firstCandidate;
+ }
+ else if (types == null)
+ {
+ for (int j = 1; j < candidates.Count; j++)
+ {
+ MethodInfo methodInfo = candidates[j];
+ if (!System.DefaultBinder.CompareMethodSigAndName(methodInfo, firstCandidate))
+ {
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+ }
+ }
+
+ // All the methods have the exact same name and sig so return the most derived one.
+ return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.ToArray(), candidates.Count) as MethodInfo;
+ }
+ }
+
+ if (binder == null)
+ binder = DefaultBinder;
+
+ return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as MethodInfo;
+ }
+
+
+ protected override ConstructorInfo GetConstructorImpl(
+ BindingFlags bindingAttr, Binder binder, CallingConventions callConvention,
+ Type[] types, ParameterModifier[] modifiers)
+ {
+ ListBuilder<ConstructorInfo> candidates = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, types, false);
+
+ if (candidates.Count == 0)
+ return null;
+
+ if (types.Length == 0 && candidates.Count == 1)
+ {
+ ConstructorInfo firstCandidate = candidates[0];
+
+ ParameterInfo[] parameters = firstCandidate.GetParametersNoCopy();
+ if (parameters == null || parameters.Length == 0)
+ {
+ return firstCandidate;
+ }
+ }
+
+ if ((bindingAttr & BindingFlags.ExactBinding) != 0)
+ return System.DefaultBinder.ExactBinding(candidates.ToArray(), types, modifiers) as ConstructorInfo;
+
+ if (binder == null)
+ binder = DefaultBinder;
+
+ return binder.SelectMethod(bindingAttr, candidates.ToArray(), 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();
+ Contract.EndContractBlock();
+
+ ListBuilder<PropertyInfo> candidates = GetPropertyCandidates(name, bindingAttr, types, false);
+
+ if (candidates.Count == 0)
+ return null;
+
+ if (types == null || types.Length == 0)
+ {
+ // no arguments
+ if (candidates.Count == 1)
+ {
+ PropertyInfo firstCandidate = candidates[0];
+
+ if ((object)returnType != null && !returnType.IsEquivalentTo(firstCandidate.PropertyType))
+ return null;
+
+ return firstCandidate;
+ }
+ else
+ {
+ if ((object)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("Arg_AmbiguousMatchException"));
+ }
+ }
+
+ if ((bindingAttr & BindingFlags.ExactBinding) != 0)
+ return System.DefaultBinder.ExactPropertyBinding(candidates.ToArray(), returnType, types, modifiers);
+
+ if (binder == null)
+ binder = DefaultBinder;
+
+ return binder.SelectProperty(bindingAttr, candidates.ToArray(), returnType, types, modifiers);
+ }
+
+
+ public override EventInfo GetEvent(String name, BindingFlags bindingAttr)
+ {
+ if (name == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ bool ignoreCase;
+ MemberListType listType;
+ RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType);
+
+ RuntimeEventInfo[] cache = Cache.GetEventList(listType, name);
+ EventInfo match = null;
+
+ bindingAttr ^= BindingFlags.DeclaredOnly;
+
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeEventInfo eventInfo = cache[i];
+ if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags)
+ {
+ if (match != null)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ match = eventInfo;
+ }
+ }
+
+ return match;
+ }
+
+ public override FieldInfo GetField(String name, BindingFlags bindingAttr)
+ {
+ if (name == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ bool ignoreCase;
+ MemberListType listType;
+ RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType);
+
+ RuntimeFieldInfo[] cache = Cache.GetFieldList(listType, name);
+ FieldInfo match = null;
+
+ bindingAttr ^= BindingFlags.DeclaredOnly;
+ bool multipleStaticFieldMatches = false;
+
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeFieldInfo fieldInfo = cache[i];
+ if ((bindingAttr & fieldInfo.BindingFlags) == fieldInfo.BindingFlags)
+ {
+ if (match != null)
+ {
+ if (Object.ReferenceEquals(fieldInfo.DeclaringType, match.DeclaringType))
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ 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("Arg_AmbiguousMatchException"));
+
+ return match;
+ }
+
+ public override Type GetInterface(String fullname, bool ignoreCase)
+ {
+ if (fullname == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ 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);
+
+ RuntimeType[] cache = Cache.GetInterfaceList(listType, name);
+
+ RuntimeType match = null;
+
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeType iface = cache[i];
+ if (RuntimeType.FilterApplyType(iface, bindingAttr, name, false, ns))
+ {
+ if (match != null)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ match = iface;
+ }
+ }
+
+ return match;
+ }
+
+ public override Type GetNestedType(String fullname, BindingFlags bindingAttr)
+ {
+ if (fullname == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ 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);
+
+ RuntimeType[] cache = Cache.GetNestedTypeList(listType, name);
+
+ RuntimeType match = null;
+
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeType nestedType = cache[i];
+ if (RuntimeType.FilterApplyType(nestedType, bindingAttr, name, false, ns))
+ {
+ if (match != null)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ match = nestedType;
+ }
+ }
+
+ return match;
+ }
+
+ public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ if (name == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ ListBuilder<MethodInfo> methods = new ListBuilder<MethodInfo>();
+ ListBuilder<ConstructorInfo> constructors = new ListBuilder<ConstructorInfo>();
+ ListBuilder<PropertyInfo> properties = new ListBuilder<PropertyInfo>();
+ ListBuilder<EventInfo> events = new ListBuilder<EventInfo>();
+ ListBuilder<FieldInfo> fields = new ListBuilder<FieldInfo>();
+ ListBuilder<Type> nestedTypes = new ListBuilder<Type>();
+
+ int totalCount = 0;
+
+ // Methods
+ if ((type & MemberTypes.Method) != 0)
+ {
+ methods = GetMethodCandidates(name, bindingAttr, CallingConventions.Any, null, true);
+ if (type == MemberTypes.Method)
+ return methods.ToArray();
+ totalCount += methods.Count;
+ }
+
+ // Constructors
+ if ((type & MemberTypes.Constructor) != 0)
+ {
+ constructors = GetConstructorCandidates(name, bindingAttr, CallingConventions.Any, null, true);
+ if (type == MemberTypes.Constructor)
+ return constructors.ToArray();
+ totalCount += constructors.Count;
+ }
+
+ // Properties
+ if ((type & MemberTypes.Property) != 0)
+ {
+ properties = GetPropertyCandidates(name, bindingAttr, null, true);
+ if (type == MemberTypes.Property)
+ return properties.ToArray();
+ totalCount += properties.Count;
+ }
+
+ // Events
+ if ((type & MemberTypes.Event) != 0)
+ {
+ events = GetEventCandidates(name, bindingAttr, true);
+ if (type == MemberTypes.Event)
+ return events.ToArray();
+ totalCount += events.Count;
+ }
+
+ // Fields
+ if ((type & MemberTypes.Field) != 0)
+ {
+ fields = GetFieldCandidates(name, bindingAttr, true);
+ if (type == MemberTypes.Field)
+ return fields.ToArray();
+ totalCount += fields.Count;
+ }
+
+ // NestedTypes
+ if ((type & (MemberTypes.NestedType | MemberTypes.TypeInfo)) != 0)
+ {
+ nestedTypes = GetNestedTypeCandidates(name, bindingAttr, true);
+ if (type == MemberTypes.NestedType || type == MemberTypes.TypeInfo)
+ return nestedTypes.ToArray();
+ totalCount += nestedTypes.Count;
+ }
+
+ MemberInfo[] compressMembers = (type == (MemberTypes.Method | MemberTypes.Constructor)) ?
+ new MethodBase[totalCount] : new MemberInfo[totalCount];
+
+ int i = 0;
+ methods.CopyTo(compressMembers, i); i += methods.Count;
+ constructors.CopyTo(compressMembers, i); i += constructors.Count;
+ properties.CopyTo(compressMembers, i); i += properties.Count;
+ events.CopyTo(compressMembers, i); i += events.Count;
+ fields.CopyTo(compressMembers, i); i += fields.Count;
+ nestedTypes.CopyTo(compressMembers, i); i += nestedTypes.Count;
+ Contract.Assert(i == compressMembers.Length);
+
+ return compressMembers;
+ }
+ #endregion
+
+ #region Identity
+ public override Module Module
+ {
+ get
+ {
+ return GetRuntimeModule();
+ }
+ }
+
+ internal RuntimeModule GetRuntimeModule()
+ {
+ return RuntimeTypeHandle.GetModule(this);
+ }
+
+ public override Assembly Assembly
+ {
+ get
+ {
+ return GetRuntimeAssembly();
+ }
+ }
+
+ internal RuntimeAssembly GetRuntimeAssembly()
+ {
+ return RuntimeTypeHandle.GetAssembly(this);
+ }
+
+ public override RuntimeTypeHandle TypeHandle
+ {
+ get
+ {
+ return new RuntimeTypeHandle(this);
+ }
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal sealed override RuntimeTypeHandle GetTypeHandleInternal()
+ {
+ return new RuntimeTypeHandle(this);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal bool IsCollectible()
+ {
+ return RuntimeTypeHandle.IsCollectible(GetTypeHandleInternal());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override TypeCode GetTypeCodeImpl()
+ {
+ TypeCode typeCode = Cache.TypeCode;
+
+ if (typeCode != TypeCode.Empty)
+ return typeCode;
+
+ CorElementType corElementType = RuntimeTypeHandle.GetCorElementType(this);
+ 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"));
+ Contract.EndContractBlock();
+
+ IRuntimeMethodInfo declaringMethod = RuntimeTypeHandle.GetDeclaringMethod(this);
+
+ if (declaringMethod == null)
+ return null;
+
+ return GetMethodBase(RuntimeMethodHandle.GetDeclaringType(declaringMethod), declaringMethod);
+ }
+ }
+ #endregion
+
+ #region Hierarchy
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsInstanceOfType(Object o)
+ {
+ return RuntimeTypeHandle.IsInstanceOfType(this, o);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Pure]
+ public override bool IsSubclassOf(Type type)
+ {
+ if ((object)type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+ RuntimeType rtType = type as RuntimeType;
+ if (rtType == null)
+ return false;
+
+ RuntimeType baseType = GetBaseType();
+
+ while (baseType != null)
+ {
+ if (baseType == rtType)
+ return true;
+
+ baseType = baseType.GetBaseType();
+ }
+
+ // 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 (rtType == RuntimeType.ObjectType && rtType != this)
+ return true;
+
+ return false;
+ }
+
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo){
+ if(typeInfo==null) return false;
+ return IsAssignableFrom(typeInfo.AsType());
+ }
+
+ public override bool IsAssignableFrom(Type c)
+ {
+ if ((object)c == null)
+ return false;
+
+ if (Object.ReferenceEquals(c, this))
+ return true;
+
+ RuntimeType fromType = c.UnderlyingSystemType as RuntimeType;
+
+ // For runtime type, let the VM decide.
+ if (fromType != null)
+ {
+ // both this and c (or their underlying system types) are runtime types
+ return RuntimeTypeHandle.CanCastTo(fromType, this);
+ }
+
+ // Special case for TypeBuilder to be backward-compatible.
+ if (c is System.Reflection.Emit.TypeBuilder)
+ {
+ // If c is a subclass of this class, then c can be cast to this type.
+ if (c.IsSubclassOf(this))
+ return true;
+
+ if (this.IsInterface)
+ {
+ return c.ImplementInterface(this);
+ }
+ else if (this.IsGenericParameter)
+ {
+ Type[] constraints = GetGenericParameterConstraints();
+ for (int i = 0; i < constraints.Length; i++)
+ if (!constraints[i].IsAssignableFrom(c))
+ return false;
+
+ return true;
+ }
+ }
+
+ // For anything else we return false.
+ return false;
+ }
+
+#if !FEATURE_CORECLR
+ // Reflexive, symmetric, transitive.
+ public override bool IsEquivalentTo(Type other)
+ {
+ RuntimeType otherRtType = other as RuntimeType;
+ if ((object)otherRtType == null)
+ return false;
+
+ if (otherRtType == this)
+ return true;
+
+ // It's not worth trying to perform further checks in managed
+ // as they would lead to FCalls anyway.
+ return RuntimeTypeHandle.IsEquivalentTo(this, otherRtType);
+ }
+#endif // FEATURE_CORECLR
+
+ public override Type BaseType
+ {
+ get
+ {
+ return GetBaseType();
+ }
+ }
+
+ private RuntimeType GetBaseType()
+ {
+ if (IsInterface)
+ return null;
+
+ if (RuntimeTypeHandle.IsGenericVariable(this))
+ {
+ Type[] constraints = GetGenericParameterConstraints();
+
+ RuntimeType baseType = RuntimeType.ObjectType;
+
+ for (int i = 0; i < constraints.Length; i++)
+ {
+ RuntimeType constraint = (RuntimeType)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 == RuntimeType.ObjectType)
+ {
+ GenericParameterAttributes special;
+ special = GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
+ if ((special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
+ baseType = RuntimeType.ValueType;
+ }
+
+ return baseType;
+ }
+
+ return RuntimeTypeHandle.GetBaseType(this);
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get
+ {
+ return this;
+ }
+ }
+ #endregion
+
+ #region Name
+ public override String FullName
+ {
+ get
+ {
+ return GetCachedName(TypeNameKind.FullName);
+ }
+ }
+
+ public override String AssemblyQualifiedName
+ {
+ get
+ {
+ string fullname = FullName;
+
+ // FullName is null if this type contains generic parameters but is not a generic type definition.
+ if (fullname == null)
+ return null;
+
+ return Assembly.CreateQualifiedName(this.Assembly.FullName, fullname);
+ }
+ }
+
+ public override String Namespace
+ {
+ get
+ {
+ string ns = Cache.GetNameSpace();
+
+ if (ns == null || ns.Length == 0)
+ return null;
+
+ return ns;
+ }
+ }
+ #endregion
+
+ #region Attributes
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override TypeAttributes GetAttributeFlagsImpl()
+ {
+ return RuntimeTypeHandle.GetAttributes(this);
+ }
+
+ public override Guid GUID
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ Guid result = new Guid ();
+ GetGUID(ref result);
+ return result;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void GetGUID(ref Guid result);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override bool IsContextfulImpl()
+ {
+ return RuntimeTypeHandle.IsContextful(this);
+ }
+
+ /*
+ protected override bool IsMarshalByRefImpl()
+ {
+ return GetTypeHandleInternal().IsMarshalByRef();
+ }
+ */
+
+ protected override bool IsByRefImpl()
+ {
+ return RuntimeTypeHandle.IsByRef(this);
+ }
+
+ protected override bool IsPrimitiveImpl()
+ {
+ return RuntimeTypeHandle.IsPrimitive(this);
+ }
+
+ protected override bool IsPointerImpl()
+ {
+ return RuntimeTypeHandle.IsPointer(this);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override bool IsCOMObjectImpl()
+ {
+ return RuntimeTypeHandle.IsComObject(this, false);
+ }
+
+#if FEATURE_COMINTEROP
+ [SecuritySafeCritical]
+ internal override bool IsWindowsRuntimeObjectImpl()
+ {
+ return IsWindowsRuntimeObjectType(this);
+ }
+
+ [SecuritySafeCritical]
+ internal override bool IsExportedToWindowsRuntimeImpl()
+ {
+ return IsTypeExportedToWindowsRuntime(this);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecurityCritical]
+ private static extern bool IsWindowsRuntimeObjectType(RuntimeType type);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecurityCritical]
+ private static extern bool IsTypeExportedToWindowsRuntime(RuntimeType type);
+
+#endif // FEATURE_COMINTEROP
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal override bool HasProxyAttributeImpl()
+ {
+ return RuntimeTypeHandle.HasProxyAttribute(this);
+ }
+
+ internal bool IsDelegate()
+ {
+ return GetBaseType() == typeof(System.MulticastDelegate);
+ }
+
+ protected override bool IsValueTypeImpl()
+ {
+ // We need to return true for generic parameters with the ValueType constraint.
+ // So we cannot use the faster RuntimeTypeHandle.IsValueType because it returns
+ // false for all generic parameters.
+ if (this == typeof(ValueType) || this == typeof(Enum))
+ return false;
+
+ return IsSubclassOf(typeof(ValueType));
+ }
+
+#if !FEATURE_CORECLR
+ public override bool IsEnum
+ {
+ get
+ {
+ return GetBaseType() == RuntimeType.EnumType;
+ }
+ }
+#endif
+
+ protected override bool HasElementTypeImpl()
+ {
+ return RuntimeTypeHandle.HasElementType(this);
+ }
+
+ public override GenericParameterAttributes GenericParameterAttributes
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (!IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
+ Contract.EndContractBlock();
+
+ GenericParameterAttributes attributes;
+
+ RuntimeTypeHandle.GetMetadataImport(this).GetGenericParamProps(MetadataToken, out attributes);
+
+ return attributes;
+ }
+ }
+
+ public override bool IsSecurityCritical
+ {
+ get { return new RuntimeTypeHandle(this).IsSecurityCritical(); }
+ }
+ public override bool IsSecuritySafeCritical
+ {
+ get { return new RuntimeTypeHandle(this).IsSecuritySafeCritical(); }
+ }
+ public override bool IsSecurityTransparent
+ {
+ get { return new RuntimeTypeHandle(this).IsSecurityTransparent(); }
+ }
+ #endregion
+
+ #region Arrays
+ internal override bool IsSzArray
+ {
+ get
+ {
+ return RuntimeTypeHandle.IsSzArray(this);
+ }
+ }
+
+ protected override bool IsArrayImpl()
+ {
+ return RuntimeTypeHandle.IsArray(this);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override int GetArrayRank()
+ {
+ if (!IsArrayImpl())
+ throw new ArgumentException(Environment.GetResourceString("Argument_HasToBeArrayClass"));
+
+ return RuntimeTypeHandle.GetArrayRank(this);
+ }
+
+ public override Type GetElementType()
+ {
+ return RuntimeTypeHandle.GetElementType(this);
+ }
+ #endregion
+
+ #region Enums
+ public override string[] GetEnumNames()
+ {
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+
+ String[] ret = Enum.InternalGetNames(this);
+
+ // Make a copy since we can't hand out the same array since users can modify them
+ String[] retVal = new String[ret.Length];
+
+ Array.Copy(ret, retVal, ret.Length);
+
+ return retVal;
+ }
+
+ [SecuritySafeCritical]
+ public override Array GetEnumValues()
+ {
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+
+ // Get all of the values
+ ulong[] values = Enum.InternalGetValues(this);
+
+ // Create a generic Array
+ Array ret = Array.UnsafeCreateInstance(this, values.Length);
+
+ for (int i = 0; i < values.Length; i++)
+ {
+ Object val = Enum.ToObject(this, values[i]);
+ ret.SetValue(val, i);
+ }
+
+ return ret;
+ }
+
+ public override Type GetEnumUnderlyingType()
+ {
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+
+ return Enum.InternalGetUnderlyingType(this);
+ }
+
+ public override bool IsEnumDefined(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ // Check if both of them are of the same type
+ RuntimeType valueType = (RuntimeType)value.GetType();
+
+ // If the value is an Enum then we need to extract the underlying value from it
+ if (valueType.IsEnum)
+ {
+ if (!valueType.IsEquivalentTo(this))
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType", valueType.ToString(), this.ToString()));
+
+ valueType = (RuntimeType)valueType.GetEnumUnderlyingType();
+ }
+
+ // If a string is passed in
+ if (valueType == RuntimeType.StringType)
+ {
+ // Get all of the Fields, calling GetHashEntry directly to avoid copying
+ string[] names = Enum.InternalGetNames(this);
+ if (Array.IndexOf(names, value) >= 0)
+ return true;
+ else
+ return false;
+ }
+
+ // If an enum or integer value is passed in
+ if (Type.IsIntegerType(valueType))
+ {
+ RuntimeType underlyingType = Enum.InternalGetUnderlyingType(this);
+ if (underlyingType != valueType)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), underlyingType.ToString()));
+
+ ulong[] ulValues = Enum.InternalGetValues(this);
+ ulong ulValue = Enum.ToUInt64(value);
+
+ return (Array.BinarySearch(ulValues, ulValue) >= 0);
+ }
+ else
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+ }
+
+ public override string GetEnumName(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ Type valueType = value.GetType();
+
+ if (!(valueType.IsEnum || IsIntegerType(valueType)))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
+
+ ulong ulValue = Enum.ToUInt64(value);
+
+ return Enum.GetEnumName(this, ulValue);
+ }
+ #endregion
+
+ #region Generics
+ internal RuntimeType[] GetGenericArgumentsInternal()
+ {
+ return GetRootElementType().GetTypeHandleInternal().GetInstantiationInternal();
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ Type[] types = GetRootElementType().GetTypeHandleInternal().GetInstantiationPublic();
+
+ if (types == null)
+ types = EmptyArray<Type>.Value;
+
+ return types;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type MakeGenericType(Type[] instantiation)
+ {
+ if (instantiation == null)
+ throw new ArgumentNullException("instantiation");
+ Contract.EndContractBlock();
+
+ RuntimeType[] instantiationRuntimeType = new RuntimeType[instantiation.Length];
+
+ if (!IsGenericTypeDefinition)
+ throw new InvalidOperationException(
+ Environment.GetResourceString("Arg_NotGenericTypeDefinition", this));
+
+ if (GetGenericArguments().Length != instantiation.Length)
+ throw new ArgumentException(Environment.GetResourceString("Argument_GenericArgsCount"), "instantiation");
+
+ for (int i = 0; i < instantiation.Length; i ++)
+ {
+ Type instantiationElem = instantiation[i];
+ if (instantiationElem == null)
+ throw new ArgumentNullException();
+
+ RuntimeType rtInstantiationElem = instantiationElem as RuntimeType;
+
+ if (rtInstantiationElem == null)
+ {
+ Type[] instantiationCopy = new Type[instantiation.Length];
+ for (int iCopy = 0; iCopy < instantiation.Length; iCopy++)
+ instantiationCopy[iCopy] = instantiation[iCopy];
+ instantiation = instantiationCopy;
+ return System.Reflection.Emit.TypeBuilderInstantiation.MakeGenericType(this, instantiation);
+ }
+
+ instantiationRuntimeType[i] = rtInstantiationElem;
+ }
+
+ RuntimeType[] genericParameters = GetGenericArgumentsInternal();
+
+ SanityCheckGenericArguments(instantiationRuntimeType, genericParameters);
+
+ Type ret = null;
+ try
+ {
+ ret = new RuntimeTypeHandle(this).Instantiate(instantiationRuntimeType);
+ }
+ catch (TypeLoadException e)
+ {
+ ValidateGenericArguments(this, instantiationRuntimeType, e);
+ throw e;
+ }
+
+ return ret;
+ }
+
+ public override bool IsGenericTypeDefinition
+ {
+ get { return RuntimeTypeHandle.IsGenericTypeDefinition(this); }
+ }
+
+ public override bool IsGenericParameter
+ {
+ get { return RuntimeTypeHandle.IsGenericVariable(this); }
+ }
+
+ public override int GenericParameterPosition
+ {
+ get
+ {
+ if (!IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
+ Contract.EndContractBlock();
+
+ return new RuntimeTypeHandle(this).GetGenericVariableIndex();
+ }
+ }
+
+ public override Type GetGenericTypeDefinition()
+ {
+ if (!IsGenericType)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotGenericType"));
+ Contract.EndContractBlock();
+
+ return RuntimeTypeHandle.GetGenericTypeDefinition(this);
+ }
+
+ public override bool IsGenericType
+ {
+ get { return RuntimeTypeHandle.HasInstantiation(this); }
+ }
+
+ public override bool IsConstructedGenericType
+ {
+ get { return IsGenericType && !IsGenericTypeDefinition; }
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get { return GetRootElementType().GetTypeHandleInternal().ContainsGenericVariables(); }
+ }
+
+ public override Type[] GetGenericParameterConstraints()
+ {
+ if (!IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
+ Contract.EndContractBlock();
+
+ Type[] constraints = new RuntimeTypeHandle(this).GetConstraints();
+
+ if (constraints == null)
+ constraints = EmptyArray<Type>.Value;
+
+ return constraints;
+ }
+ #endregion
+
+ #region Misc
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type MakePointerType() { return new RuntimeTypeHandle(this).MakePointer(); }
+ public override Type MakeByRefType() { return new RuntimeTypeHandle(this).MakeByRef(); }
+ public override Type MakeArrayType() { return new RuntimeTypeHandle(this).MakeSZArray(); }
+ public override Type MakeArrayType(int rank)
+ {
+ if (rank <= 0)
+ throw new IndexOutOfRangeException();
+ Contract.EndContractBlock();
+
+ return new RuntimeTypeHandle(this).MakeArray(rank);
+ }
+ public override StructLayoutAttribute StructLayoutAttribute
+ {
+ [System.Security.SecuritySafeCritical] // overrides transparent public member
+ 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 RuntimeType s_typedRef = (RuntimeType)typeof(TypedReference);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static private extern bool CanValueSpecialCast(RuntimeType valueType, RuntimeType targetType);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static private extern Object AllocateValueType(RuntimeType type, object value, bool fForceTypeChange);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe Object CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
+ {
+ // this method is used by invocation in reflection to check whether a value can be assigned to type.
+ if (IsInstanceOfType(value))
+ {
+ // Since this cannot be a generic parameter, we use RuntimeTypeHandle.IsValueType here
+ // because it is faster than RuntimeType.IsValueType
+ Contract.Assert(!IsGenericParameter);
+
+ Type type = null;
+
+#if FEATURE_REMOTING
+ // For the remoting objects Object.GetType goes through proxy. Avoid the proxy call and just get
+ // the type directly. It is necessary to support proxies that do not handle GetType.
+ RealProxy realProxy = System.Runtime.Remoting.RemotingServices.GetRealProxy(value);
+
+ if (realProxy != null)
+ {
+ type = realProxy.GetProxiedType();
+ }
+ else
+ {
+ type = value.GetType();
+ }
+#else
+ type = value.GetType();
+#endif
+
+ if (!Object.ReferenceEquals(type, this) && RuntimeTypeHandle.IsValueType(this))
+ {
+ // must be an equivalent type, re-box to the target type
+ return AllocateValueType(this, value, true);
+ }
+ else
+ {
+ return value;
+ }
+ }
+
+ // if this is a ByRef get the element type and check if it's compatible
+ bool isByRef = IsByRef;
+ if (isByRef)
+ {
+ RuntimeType elementType = RuntimeTypeHandle.GetElementType(this);
+ 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 AllocateValueType(elementType, value, false);
+ }
+ }
+ else if (value == null)
+ return value;
+ else if (this == s_typedRef)
+ // everything works for a typedref
+ return value;
+
+ // check the strange ones courtesy of reflection:
+ // - implicit cast between primitives
+ // - enum treated as underlying type
+ // - IntPtr and System.Reflection.Pointer to pointer types
+ bool needsSpecialCast = IsPointer || IsEnum || IsPrimitive;
+ if (needsSpecialCast)
+ {
+ RuntimeType valueType;
+ Pointer pointer = value as Pointer;
+ if (pointer != null)
+ valueType = pointer.GetPointerType();
+ else
+ valueType = (RuntimeType)value.GetType();
+
+ if (CanValueSpecialCast(valueType, this))
+ {
+ 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));
+
+ return TryChangeType(value, binder, culture, needsSpecialCast);
+ }
+
+ // Factored out of CheckValue to reduce code complexity.
+ [System.Security.SecurityCritical]
+ private Object TryChangeType(Object value, Binder binder, CultureInfo culture, bool needsSpecialCast)
+ {
+ 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 check if it's compatible
+ if (IsByRef)
+ {
+ RuntimeType elementType = RuntimeTypeHandle.GetElementType(this);
+ if (elementType.IsInstanceOfType(value) || value == null)
+ return AllocateValueType(elementType, value, false);
+ }
+ else if (value == null)
+ return value;
+ if (needsSpecialCast)
+ {
+ RuntimeType valueType;
+ Pointer pointer = value as Pointer;
+ if (pointer != null)
+ valueType = pointer.GetPointerType();
+ else
+ valueType = (RuntimeType)value.GetType();
+
+ if (CanValueSpecialCast(valueType, this))
+ {
+ if (pointer != null)
+ return pointer.GetPointerValue();
+ else
+ return value;
+ }
+ }
+ }
+
+ throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
+ }
+
+ // GetDefaultMembers
+ // This will return a MemberInfo that has been marked with the [DefaultMemberAttribute]
+ public override MemberInfo[] GetDefaultMembers()
+ {
+ // See if we have cached the default member name
+ MemberInfo[] members = null;
+
+ String defaultMemberName = GetDefaultMemberName();
+ if (defaultMemberName != null)
+ {
+ members = GetMember(defaultMemberName);
+ }
+
+ if (members == null)
+ members = EmptyArray<MemberInfo>.Value;
+
+ return members;
+ }
+
+#if FEATURE_COMINTEROP
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ [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"));
+ Contract.EndContractBlock();
+
+ #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 && FEATURE_USE_LCID
+ 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 FEATURE_REMOTING
+ if(!RemotingServices.IsTransparentProxy(target))
+#endif
+ {
+ #region Non-TransparentProxy case
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ bool[] isByRef = modifiers == null ? null : modifiers[0].IsByRefArray;
+
+ // pass LCID_ENGLISH_US if no explicit culture is specified to match the behavior of VB
+ int lcid = (culture == null ? 0x0409 : culture.LCID);
+
+ return InvokeDispMethod(name, bindingFlags, target, providedArgs, isByRef, lcid, namedParams);
+ #endregion
+ }
+#if FEATURE_REMOTING
+ else
+ {
+ #region TransparentProxy case
+ return ((MarshalByRefObject)target).InvokeMember(name, bindingFlags, binder, providedArgs, modifiers, culture, namedParams);
+ #endregion
+ }
+#endif // FEATURE_REMOTING
+ }
+#endif // FEATURE_COMINTEROP && FEATURE_USE_LCID
+ #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
+ {
+ Contract.Assert(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[];
+
+ Contract.Assert(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 || Object.ReferenceEquals(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<idxCnt;i++)
+ {
+ try
+ {
+ idx[i] = ((IConvertible)providedArgs[i]).ToInt32(null);
+ }
+ catch (InvalidCastException)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_IndexMustBeInt"));
+ }
+ }
+
+ // Set or get the value...
+ Array a = (Array) selFld.GetValue(target);
+
+ // Set or get the value in the array
+ if ((bindingFlags & BindingFlags.GetField) != 0)
+ {
+ return a.GetValue(idx);
+ }
+ else
+ {
+ a.SetValue(providedArgs[idxCnt],idx);
+ return null;
+ }
+ }
+ #endregion
+ }
+
+ if (IsGetField)
+ {
+ #region Get the field value
+ if (argCnt != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_FldGetArgErr"),"bindingFlags");
+
+ return selFld.GetValue(target);
+ #endregion
+ }
+ else
+ {
+ #region Set the field Value
+ if (argCnt != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_FldSetArgErr"),"bindingFlags");
+
+ selFld.SetValue(target,providedArgs[0],bindingFlags,binder,culture);
+
+ return null;
+ #endregion
+ }
+ #endregion
+ }
+
+ if ((bindingFlags & BinderNonFieldGetSet) == 0)
+ throw new MissingFieldException(FullName, name);
+ }
+ #endregion
+
+ #region Caching Logic
+ /*
+ bool useCache = false;
+
+ // Note that when we add something to the cache, we are careful to ensure
+ // that the actual providedArgs matches the parameters of the method. Otherwise,
+ // some default argument processing has occurred. We don't want anyone
+ // else with the same (insufficient) number of actual arguments to get a
+ // cache hit because then they would bypass the default argument processing
+ // and the invocation would fail.
+ if (bDefaultBinder && namedParams == null && argCnt < 6)
+ useCache = true;
+
+ if (useCache)
+ {
+ MethodBase invokeMethod = GetMethodFromCache (name, bindingFlags, argCnt, providedArgs);
+
+ if (invokeMethod != null)
+ return ((MethodInfo) invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture);
+ }
+ */
+ #endregion
+
+ #region Property PreConditions
+ // @Legacy - This is RTM behavior
+ bool isGetProperty = (bindingFlags & BindingFlags.GetProperty) != 0;
+ bool isSetProperty = (bindingFlags & BindingFlags.SetProperty) != 0;
+
+ if (isGetProperty || isSetProperty)
+ {
+ #region Preconditions
+ if (isGetProperty)
+ {
+ Contract.Assert(!IsSetField);
+
+ if (isSetProperty)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), "bindingFlags");
+ }
+ else
+ {
+ Contract.Assert(isSetProperty);
+
+ Contract.Assert(!IsGetField);
+
+ if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), "bindingFlags");
+ }
+ #endregion
+ }
+ #endregion
+
+ MethodInfo[] finalists = null;
+ MethodInfo finalist = null;
+
+ #region BindingFlags.InvokeMethod
+ if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
+ {
+ #region Lookup Methods
+ MethodInfo[] semiFinalists = GetMember(name, MemberTypes.Method, bindingFlags) as MethodInfo[];
+ List<MethodInfo> results = null;
+
+ for(int i = 0; i < semiFinalists.Length; i ++)
+ {
+ MethodInfo semiFinalist = semiFinalists[i];
+ Contract.Assert(semiFinalist != null);
+
+ if (!FilterApplyMethodInfo((RuntimeMethodInfo)semiFinalist, bindingFlags, CallingConventions.Any, new Type[argCnt]))
+ continue;
+
+ if (finalist == null)
+ {
+ finalist = semiFinalist;
+ }
+ else
+ {
+ if (results == null)
+ {
+ results = new List<MethodInfo>(semiFinalists.Length);
+ results.Add(finalist);
+ }
+
+ results.Add(semiFinalist);
+ }
+ }
+
+ if (results != null)
+ {
+ Contract.Assert(results.Count > 1);
+ finalists = new MethodInfo[results.Count];
+ results.CopyTo(finalists);
+ }
+ #endregion
+ }
+ #endregion
+
+ Contract.Assert(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[];
+ List<MethodInfo> 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 (!FilterApplyMethodInfo((RuntimeMethodInfo)semiFinalist, bindingFlags, CallingConventions.Any, new Type[argCnt]))
+ continue;
+
+ if (finalist == null)
+ {
+ finalist = semiFinalist;
+ }
+ else
+ {
+ if (results == null)
+ {
+ results = new List<MethodInfo>(semiFinalists.Length);
+ results.Add(finalist);
+ }
+
+ results.Add(semiFinalist);
+ }
+ }
+
+ if (results != null)
+ {
+ Contract.Assert(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 = EmptyArray<Object>.Value;
+
+ 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
+ [Pure]
+ public override bool Equals(object obj)
+ {
+ // ComObjects are identified by the instance of the Type object and not the TypeHandle.
+ return obj == (object)this;
+ }
+
+ public override int GetHashCode()
+ {
+ return RuntimeHelpers.GetHashCode(this);
+ }
+
+#if !FEATURE_CORECLR
+ public static bool operator ==(RuntimeType left, RuntimeType right)
+ {
+ return object.ReferenceEquals(left, right);
+ }
+
+ public static bool operator !=(RuntimeType left, RuntimeType right)
+ {
+ return !object.ReferenceEquals(left, right);
+ }
+#endif // !FEATURE_CORECLR
+
+ public override String ToString()
+ {
+ return GetCachedName(TypeNameKind.ToString);
+ }
+ #endregion
+
+ #region ICloneable
+ public Object Clone()
+ {
+ return this;
+ }
+ #endregion
+
+ #region ISerializable
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ UnitySerializationHolder.GetUnitySerializationInfo(info, this);
+ }
+ #endregion
+
+ #region ICustomAttributeProvider
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return CustomAttribute.GetCustomAttributes(this, RuntimeType.ObjectType, inherit);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if ((object)attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType, inherit);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if ((object)attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType, inherit);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+ #endregion
+
+ #region MemberInfo Overrides
+ public override String Name
+ {
+ get
+ {
+ return GetCachedName(TypeNameKind.Name);
+ }
+ }
+
+ // This is used by the ToString() overrides of all reflection types. The legacy behavior has the following problems:
+ // 1. Use only Name for nested types, which can be confused with global types and generic parameters of the same name.
+ // 2. Use only Name for generic parameters, which can be confused with nested types and global types of the same name.
+ // 3. Remove the namespace ("System") for all primitive types, which is not language neutral.
+ // 4. MethodBase.ToString() use "ByRef" for byref parameters which is different than Type.ToString().
+ // 5. ConstructorInfo.ToString() outputs "Void" as the return type. Why Void?
+ // Since it could be a breaking changes to fix these legacy behaviors, we only use the better and more unambiguous format
+ // in serialization (MemberInfoSerializationHolder).
+ internal override string FormatTypeName(bool serialization)
+ {
+ if (serialization)
+ {
+ return GetCachedName(TypeNameKind.SerializationName);
+ }
+ else
+ {
+ Type elementType = GetRootElementType();
+
+ // Legacy: this doesn't make sense, why use only Name for nested types but otherwise
+ // ToString() which contains namespace.
+ if (elementType.IsNested)
+ return Name;
+
+ string typeName = ToString();
+
+ // Legacy: why removing "System"? Is it just because C# has keywords for these types?
+ // If so why don't we change it to lower case to match the C# keyword casing?
+ if (elementType.IsPrimitive ||
+ elementType == typeof(void) ||
+ elementType == typeof(TypedReference))
+ {
+ typeName = typeName.Substring(@"System.".Length);
+ }
+
+ return typeName;
+ }
+ }
+
+ private string GetCachedName(TypeNameKind kind)
+ {
+ return Cache.GetName(kind);
+ }
+
+ 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
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return RuntimeTypeHandle.GetToken(this);
+ }
+ }
+ #endregion
+
+ #region Legacy Internal
+ private void CreateInstanceCheckThis()
+ {
+ if (this is ReflectionOnlyType)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ReflectionOnlyInvoke"));
+
+ if (ContainsGenericParameters)
+ throw new ArgumentException(
+ Environment.GetResourceString("Acc_CreateGenericEx", this));
+ Contract.EndContractBlock();
+
+ Type elementType = this.GetRootElementType();
+
+ if (Object.ReferenceEquals(elementType, typeof(ArgIterator)))
+ throw new NotSupportedException(Environment.GetResourceString("Acc_CreateArgIterator"));
+
+ if (Object.ReferenceEquals(elementType, typeof(void)))
+ throw new NotSupportedException(Environment.GetResourceString("Acc_CreateVoid"));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Object CreateInstanceImpl(
+ BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, ref StackCrawlMark stackMark)
+ {
+ 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 FEATURE_REMOTING
+ if(null != activationAttributes)
+ {
+ ActivationServices.PushActivationAttributes(this, activationAttributes);
+ }
+#endif
+
+ if (args == null)
+ args = EmptyArray<Object>.Value;
+
+ 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() || IsValueType))
+ {
+ server = CreateInstanceDefaultCtor((bindingAttr & BindingFlags.NonPublic) == 0 , false, true, ref stackMark);
+ }
+ else
+ {
+ ConstructorInfo[] candidates = GetConstructors(bindingAttr);
+ List<MethodBase> matches = new List<MethodBase>(candidates.Length);
+
+ // We cannot use Type.GetTypeArray here because some of the args might be null
+ 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 ++)
+ {
+ if (FilterApplyConstructorInfo((RuntimeConstructorInfo)candidates[i], bindingAttr, CallingConventions.Any, argsType))
+ 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 FEATURE_REMOTING
+ if(null != activationAttributes)
+ {
+ ActivationServices.PopActivationAttributes(this);
+ activationAttributes = null;
+ }
+#endif
+ throw new MissingMethodException(Environment.GetResourceString("MissingConstructor_Name", FullName));
+ }
+
+ 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)
+ {
+#if FEATURE_REMOTING
+ // Null out activation attributes before throwing exception
+ if(null != activationAttributes)
+ {
+ ActivationServices.PopActivationAttributes(this);
+ activationAttributes = null;
+ }
+#endif
+ throw new MissingMethodException(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 (RuntimeType.DelegateType.IsAssignableFrom(invokeMethod.DeclaringType))
+ {
+#if FEATURE_CORECLR
+ // In CoreCLR, CAS is not exposed externally. So what we really are looking
+ // for is to see if the external caller of this API is transparent or not.
+ // We get that information from the fact that a Demand will succeed only if
+ // the external caller is not transparent.
+ try
+ {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+ }
+ catch
+ {
+ throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("NotSupported_DelegateCreationFromPT")));
+ }
+#else // FEATURE_CORECLR
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#endif // FEATURE_CORECLR
+ }
+
+ if (invokeMethod.GetParametersNoCopy().Length == 0)
+ {
+ if (args.Length != 0)
+ {
+
+ Contract.Assert((invokeMethod.CallingConvention & CallingConventions.VarArgs) ==
+ CallingConventions.VarArgs);
+ throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture,
+ Environment.GetResourceString("NotSupported_CallToVarArg")));
+ }
+
+ // fast path??
+ server = Activator.CreateInstance(this, true);
+ }
+ else
+ {
+ server = ((ConstructorInfo)invokeMethod).Invoke(bindingAttr, binder, args, culture);
+ if (state != null)
+ binder.ReorderArgumentArray(ref args, state);
+ }
+ }
+ }
+ finally
+ {
+#if FEATURE_REMOTING
+ // Reset the TLS to null
+ if(null != activationAttributes)
+ {
+ ActivationServices.PopActivationAttributes(this);
+ activationAttributes = null;
+ }
+#endif
+ }
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+
+ //Console.WriteLine(server);
+ return server;
+ }
+
+ // the cache entry
+ class ActivatorCacheEntry
+ {
+ // the type to cache
+ internal readonly RuntimeType m_type;
+ // the delegate containing the call to the ctor, will be replaced by an IntPtr to feed a calli with
+ internal volatile CtorDelegate m_ctor;
+ internal readonly RuntimeMethodHandleInternal m_hCtorMethodHandle;
+ internal readonly MethodAttributes m_ctorAttributes;
+ // Is a security check needed before this constructor is invoked?
+ internal readonly bool m_bNeedSecurityCheck;
+ // Lazy initialization was performed
+ internal volatile bool m_bFullyInitialized;
+
+ [System.Security.SecurityCritical]
+ internal ActivatorCacheEntry(RuntimeType t, RuntimeMethodHandleInternal rmh, bool bNeedSecurityCheck)
+ {
+ m_type = t;
+ m_bNeedSecurityCheck = bNeedSecurityCheck;
+ m_hCtorMethodHandle = rmh;
+ if (!m_hCtorMethodHandle.IsNullHandle())
+ m_ctorAttributes = RuntimeMethodHandle.GetAttributes(m_hCtorMethodHandle);
+ }
+ }
+
+ //ActivatorCache
+ class ActivatorCache
+ {
+ const int CACHE_SIZE = 16;
+ volatile int hash_counter; //Counter for wrap around
+ readonly ActivatorCacheEntry[] cache = new ActivatorCacheEntry[CACHE_SIZE];
+
+ volatile ConstructorInfo delegateCtorInfo;
+ volatile 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));
+#pragma warning disable 618
+ ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode));
+#pragma warning restore 618
+ delegateCreatePermissions = ps;
+
+ ConstructorInfo ctorInfo = typeof(CtorDelegate).GetConstructor(new Type[] {typeof(Object), typeof(IntPtr)});
+ delegateCtorInfo = ctorInfo; // this assignment should be last
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private void InitializeCacheEntry(ActivatorCacheEntry ace)
+ {
+ if (!ace.m_type.IsValueType)
+ {
+ Contract.Assert(!ace.m_hCtorMethodHandle.IsNullHandle(), "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, RuntimeMethodHandle.GetFunctionPointer(ace.m_hCtorMethodHandle) });
+ ace.m_ctor = ctor;
+ }
+ ace.m_bFullyInitialized = true;
+ }
+
+ internal ActivatorCacheEntry GetEntry(RuntimeType t)
+ {
+ int index = hash_counter;
+ for(int i = 0; i < CACHE_SIZE; i++)
+ {
+ ActivatorCacheEntry ace = Volatile.Read(ref cache[index]);
+ if (ace != null && ace.m_type == t) //check for type match..
+ {
+ 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;
+ Volatile.Write(ref cache[index], ace);
+ }
+ }
+
+ private static volatile ActivatorCache s_ActivatorCache;
+
+ // the slow path of CreateInstanceDefaultCtor
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal Object CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
+ {
+ RuntimeMethodHandleInternal runtime_ctor = default(RuntimeMethodHandleInternal);
+ bool bNeedSecurityCheck = true;
+ bool bCanBeCached = false;
+ bool bSecurityCheckOff = false;
+
+ if (!skipCheckThis)
+ CreateInstanceCheckThis();
+
+ if (!fillCache)
+ bSecurityCheckOff = true;
+
+#if FEATURE_APPX
+ INVOCATION_FLAGS invocationFlags = InvocationFlags;
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ {
+ RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ if (caller != null && !caller.IsSafeForReflection())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", this.FullName));
+
+ // Allow it because the caller is framework code, but don't cache the result
+ // because we need to do the stack walk every time this type is instantiated.
+ bSecurityCheckOff = false;
+ bCanBeCached = false;
+ }
+#endif
+#if FEATURE_CORECLR
+ bSecurityCheckOff = true; // CoreCLR does not use security at all.
+#endif
+
+ 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();
+ s_ActivatorCache = activatorCache;
+ }
+
+ // cache the ctor
+ ActivatorCacheEntry ace = new ActivatorCacheEntry(this, runtime_ctor, bNeedSecurityCheck);
+ activatorCache.SetEntry(ace);
+ }
+
+ return instance;
+ }
+
+ // Helper to invoke the default (parameterless) ctor.
+ // fillCache is set in the SL2/3 compat mode or when called from Marshal.PtrToStructure.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ internal Object CreateInstanceDefaultCtor(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
+ {
+ if (GetType() == typeof(ReflectionOnlyType))
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly"));
+
+ ActivatorCache activatorCache = s_ActivatorCache;
+ if (activatorCache != null)
+ {
+ ActivatorCacheEntry ace = activatorCache.GetEntry(this);
+ if (ace != null)
+ {
+ if (publicOnly)
+ {
+ if (ace.m_ctor != null &&
+ (ace.m_ctorAttributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
+ {
+ throw new MissingMethodException(Environment.GetResourceString("Arg_NoDefCTor"));
+ }
+ }
+
+ // Allocate empty object
+ Object instance = RuntimeTypeHandle.Allocate(this);
+
+ // if m_ctor is null, this type doesn't have a default ctor
+ Contract.Assert(ace.m_ctor != null || this.IsValueType);
+
+ if (ace.m_ctor != null)
+ {
+#if !FEATURE_CORECLR
+ // Perform security checks if needed
+ if (ace.m_bNeedSecurityCheck)
+ RuntimeMethodHandle.PerformSecurityCheck(instance, ace.m_hCtorMethodHandle, this, (uint)INVOCATION_FLAGS.INVOCATION_FLAGS_CONSTRUCTOR_INVOKE);
+#endif
+
+ // Call ctor (value types wont have any)
+ try
+ {
+ ace.m_ctor(instance);
+ }
+ catch (Exception e)
+ {
+ throw new TargetInvocationException(e);
+ }
+ }
+ return instance;
+ }
+ }
+ return CreateInstanceSlow(publicOnly, skipCheckThis, fillCache, ref stackMark);
+ }
+
+ internal void InvalidateCachedNestedType()
+ {
+ Cache.InvalidateCachedNestedType();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsGenericCOMObjectImpl()
+ {
+ return RuntimeTypeHandle.IsComObject(this, true);
+ }
+ #endregion
+
+ #region Legacy Static Internal
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Object _CreateEnum(RuntimeType enumType, long value);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Object CreateEnum(RuntimeType enumType, long value)
+ {
+ return _CreateEnum(enumType, value);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern Object InvokeDispMethod(
+ String name, BindingFlags invokeAttr, Object target, Object[] args,
+ bool[] byrefModifiers, int culture, String[] namedParameters);
+
+#if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError);
+#else // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
+ internal static Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError)
+ {
+ throw new NotImplementedException("CoreCLR_REMOVED -- Unmanaged activation removed");
+ }
+
+ internal static Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError)
+ {
+ throw new NotImplementedException("CoreCLR_REMOVED -- Unmanaged activation removed");
+ }
+#endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
+
+ #endregion
+
+ #region COM
+#if FEATURE_COMINTEROP && FEATURE_REMOTING
+ [System.Security.SecuritySafeCritical] // auto-generated
+ 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 (Object.ReferenceEquals(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 (!Object.ReferenceEquals(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 (!Object.ReferenceEquals(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;
+ }
+
+ [SecuritySafeCritical]
+ 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:
+ Contract.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.UnsafeCreateInstance(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:
+ Contract.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 volatile OleAutBinder s_ForwardCallBinder;
+#endif // FEATURE_COMINTEROP && FEATURE_REMOTING
+ #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"));
+ }
+ }
+
+ }
+
+ #region Library
+ internal unsafe struct Utf8String
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern unsafe bool EqualsCaseSensitive(void* szLhs, void* szRhs, int cSz);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern unsafe bool EqualsCaseInsensitive(void* szLhs, void* szRhs, int cSz);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern unsafe uint HashCaseInsensitive(void* sz, int cSz);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static int GetUtf8StringByteLength(void* pUtf8String)
+ {
+ int len = 0;
+
+ unsafe
+ {
+ byte* pItr = (byte*)pUtf8String;
+
+ while (*pItr != 0)
+ {
+ len++;
+ pItr++;
+ }
+ }
+
+ return len;
+ }
+
+ [SecurityCritical]
+ private void* m_pStringHeap; // This is the raw UTF8 string.
+ private int m_StringHeapByteLength;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Utf8String(void* pStringHeap)
+ {
+ m_pStringHeap = pStringHeap;
+ if (pStringHeap != null)
+ {
+ m_StringHeapByteLength = GetUtf8StringByteLength(pStringHeap);
+ }
+ else
+ {
+ m_StringHeapByteLength = 0;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe Utf8String(void* pUtf8String, int cUtf8String)
+ {
+ m_pStringHeap = pUtf8String;
+ m_StringHeapByteLength = cUtf8String;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ 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;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ 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;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe uint HashCaseInsensitive()
+ {
+ return Utf8String.HashCaseInsensitive(m_pStringHeap, m_StringHeapByteLength);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ 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);
+ }
+ }
+ }
+ #endregion
+}
+
+namespace System.Reflection
+{
+ // Reliable hashtable thread safe for multiple readers and single writer. Note that the reliability goes together with thread
+ // safety. Thread safety for multiple readers requires atomic update of the state that also makes makes the table
+ // reliable in the presence of asynchronous exceptions.
+ internal struct CerHashtable<K, V> where K : class
+ {
+ private class Table
+ {
+ // Note that m_keys and m_values arrays are immutable to allow lock-free reads. A new instance
+ // of CerHashtable has to be allocated to grow the size of the hashtable.
+ internal K[] m_keys;
+ internal V[] m_values;
+ internal int m_count;
+
+ internal Table(int size)
+ {
+ size = HashHelpers.GetPrime(size);
+ m_keys = new K[size];
+ m_values = new V[size];
+ }
+
+ internal void Insert(K key, V value)
+ {
+
+ int hashcode = GetHashCodeHelper(key);
+ if (hashcode < 0)
+ hashcode = ~hashcode;
+
+ K[] keys = m_keys;
+ int index = hashcode % keys.Length;
+
+ while (true)
+ {
+ K hit = keys[index];
+
+ if (hit == null)
+ {
+ m_count++;
+ m_values[index] = value;
+
+ // This volatile write has to be last. It is going to publish the result atomically.
+ //
+ // Note that incrementing the count or setting the value does not do any harm without setting the key. The inconsistency will be ignored
+ // and it will go away completely during next rehash.
+ Volatile.Write(ref keys[index], key);
+
+ break;
+ }
+ else
+ {
+ Contract.Assert(!hit.Equals(key), "Key was already in CerHashtable! Potential race condition (or bug) in the Reflection cache?");
+
+ index++;
+ if (index >= keys.Length)
+ index -= keys.Length;
+ }
+ }
+ }
+ }
+
+ private Table m_Table;
+
+ private const int MinSize = 7;
+
+ private static int GetHashCodeHelper(K key)
+ {
+ string sKey = key as string;
+
+ // For strings we don't want the key to differ across domains as CerHashtable might be shared.
+ if(sKey == null)
+ {
+ return key.GetHashCode();
+
+ }
+ else
+ {
+ return sKey.GetLegacyNonRandomizedHashCode();
+ }
+ }
+
+ private void Rehash(int newSize)
+ {
+ Table newTable = new Table(newSize);
+
+ Table oldTable = m_Table;
+ if (oldTable != null)
+ {
+ K[] keys = oldTable.m_keys;
+ V[] values = oldTable.m_values;
+
+ for (int i = 0; i < keys.Length; i++)
+ {
+ K key = keys[i];
+
+ if (key != null)
+ {
+ newTable.Insert(key, values[i]);
+ }
+ }
+ }
+
+ // Publish the new table atomically
+ Volatile.Write(ref m_Table, newTable);
+ }
+
+ internal V this[K key]
+ {
+ set
+ {
+ Table table = m_Table;
+
+ if (table != null)
+ {
+ int requiredSize = 2 * (table.m_count + 1);
+ if (requiredSize >= table.m_keys.Length)
+ Rehash(requiredSize);
+ }
+ else
+ {
+ Rehash(MinSize);
+ }
+
+ m_Table.Insert(key, value);
+ }
+ get
+ {
+ Table table = Volatile.Read(ref m_Table);
+ if (table == null)
+ return default(V);
+
+ int hashcode = GetHashCodeHelper(key);
+ if (hashcode < 0)
+ hashcode = ~hashcode;
+
+ K[] keys = table.m_keys;
+ int index = hashcode % keys.Length;
+
+ while (true)
+ {
+ // This volatile read has to be first. It is reading the atomically published result.
+ K hit = Volatile.Read(ref keys[index]);
+
+ if (hit != null)
+ {
+ if (hit.Equals(key))
+ return table.m_values[index];
+
+ index++;
+ if (index >= keys.Length)
+ index -= keys.Length;
+ }
+ else
+ {
+ return default(V);
+ }
+ }
+ }
+ }
+ }
+}