public static void Refresh(Type type)
{
if (type == 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
// type. We will invalidate the metadata at
// each of these levels.
bool found = false;
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 only clear our filter and fire the refresh event if there was one or
// more type description providers that were populated with metdata.
// This prevents us from doing a lot of extra work and raising
// a ton more events than we need to.
//
if (found)
{
Interlocked.Increment(ref s_metadataVersion);
// And raise the event.
//
RaiseRefresh(type);
}
}