private static bool _Verify(CacheFixEntry entry, Type type) { object cache; Array properties, fields; // The cache can sometimes be invalidated. // TODO: Figure out if only the arrays get replaced or if the entire cache object gets replaced! if (entry.Cache != (cache = p_RuntimeType_Cache.GetValue(type, _NoArgs))) { entry.Cache = cache; entry.Properties = _GetArray(cache, m_RuntimeTypeCache_GetPropertyList); entry.Fields = _GetArray(cache, m_RuntimeTypeCache_GetFieldList); return(false); } else if (entry.Properties != (properties = _GetArray(cache, m_RuntimeTypeCache_GetPropertyList))) { entry.Properties = properties; entry.Fields = _GetArray(cache, m_RuntimeTypeCache_GetFieldList); return(false); } else if (entry.Fields != (fields = _GetArray(cache, m_RuntimeTypeCache_GetFieldList))) { entry.Fields = fields; return(false); } else { // Cache should still be the same, no re-fix necessary. return(true); } }
public static void FixReflectionCache(this Type type) { if (t_RuntimeType == null || p_RuntimeType_Cache == null || m_RuntimeTypeCache_GetFieldList == null || m_RuntimeTypeCache_GetPropertyList == null) { return; } for (; type != null; type = type.DeclaringType) { // All types SHOULD inherit RuntimeType, including those built at runtime. // One might never know what awaits us in the depths of reflection hell though. if (!t_RuntimeType.IsInstanceOfType(type)) { continue; } CacheFixEntry entry = _CacheFixed.GetValue(type, rt => { CacheFixEntry entryNew = new CacheFixEntry(); object cache; Array properties, fields; // All RuntimeTypes MUST have a cache, the getter is non-virtual, it creates on demand and asserts non-null. entryNew.Cache = cache = p_RuntimeType_Cache.GetValue(rt, _NoArgs); entryNew.Properties = properties = _GetArray(cache, m_RuntimeTypeCache_GetPropertyList); entryNew.Fields = fields = _GetArray(cache, m_RuntimeTypeCache_GetFieldList); _FixReflectionCacheOrder <PropertyInfo>(properties); _FixReflectionCacheOrder <FieldInfo>(fields); entryNew.NeedsVerify = false; return(entryNew); }); if (entry.NeedsVerify && !_Verify(entry, type)) { lock (entry) { _FixReflectionCacheOrder <PropertyInfo>(entry.Properties); _FixReflectionCacheOrder <FieldInfo>(entry.Fields); } } entry.NeedsVerify = true; } }