Example #1
0
        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);
            }
        }
Example #2
0
        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;
            }
        }