private static void Refresh(object component, bool refreshReflectionProvider)
{
if (component == null)
{
Debug.Fail("COMPAT: Returning, but you should not pass null here");
return;
}
// Build up a list of type description providers for
// each type that is a derived type of the given
// object. We will invalidate the metadata at
// each of these levels.
bool found = false;
if (refreshReflectionProvider)
{
Type type = component.GetType();
lock (s_providerTable)
{
// ReflectTypeDescritionProvider is only bound to object, but we
// need go to through the entire table to try to find custom
// providers. If we find one, will clear our cache.
// Manual use of IDictionaryEnumerator instead of foreach to avoid
// DictionaryEntry box allocations.
IDictionaryEnumerator e = s_providerTable.GetEnumerator();
while (e.MoveNext())
{
DictionaryEntry de = e.Entry;
Type nodeType = de.Key as Type;
if (nodeType != null && type.GetTypeInfo().IsAssignableFrom(nodeType) || nodeType == typeof(object))
{
TypeDescriptionNode node = (TypeDescriptionNode)de.Value;
while (node != null && !(node.Provider is ReflectTypeDescriptionProvider))
{
found = true;
node = node.Next;
}
if (node != null)
{
ReflectTypeDescriptionProvider provider = (ReflectTypeDescriptionProvider)node.Provider;
if (provider.IsPopulated(type))
{
found = true;
provider.Refresh(type);
}
}
}
}
}
}
// We need to clear our filter even if no typedescriptionprovider had data.
// This is because if you call Refresh(instance1) and Refresh(instance2)
// and instance1 and instance2 are of the same type, you will end up not
// actually deleting the dictionary cache on instance2 if you skip this
// when you don't find a typedescriptionprovider.
// However, we do not need to fire the event if we did not find any loaded
// typedescriptionprovider AND the cache is empty (if someone repeatedly calls
// Refresh on an instance).
// Now, clear any cached data for the instance.
//
IDictionary cache = GetCache(component);
if (found || cache != null)
{
if (cache != null)
{
for (int idx = 0; idx < s_pipelineFilterKeys.Length; idx++)
{
cache.Remove(s_pipelineFilterKeys[idx]);
cache.Remove(s_pipelineMergeKeys[idx]);
cache.Remove(s_pipelineAttributeFilterKeys[idx]);
}
}
Interlocked.Increment(ref s_metadataVersion);
// And raise the event.
//
RaiseRefresh(component);
}
}