public AttributeCollection GetAttributes(object component) {
// Another worst case collision scenario: we don't want the perf hit
// of taking a lock.
//
if (this.attributes == null) {
this.attributes = new AttributeCollection(new MemberList(this).GetAttributes());
}
AttributeCollection filteredAttributes = attributes;
if (component is IComponent) {
ITypeDescriptorFilterService tf = (ITypeDescriptorFilterService)GetService(component, typeof(ITypeDescriptorFilterService));
if (tf != null) {
// The component's site is interested in filtering attributes. See if we
// have filtered them before. If so, then we're done. Otherwise we
// need to filter.
//
IDictionaryService ds = (IDictionaryService)GetService(component, typeof(IDictionaryService));
if (ds != null) {
AttributeCollection savedAttributes = null;
lock(ds) {
savedAttributes = (AttributeCollection)ds.GetValue(typeof(AttributeCollection));
}
if (savedAttributes != null) {
// Check that the filter that was used to create these attributes is the same
// filter we currently have. People may replace the filter, and if we do
// we must refresh the cache.
//
object savedFilter = ds.GetValue(typeof(ITypeDescriptorFilterService));
if (savedFilter == null || savedFilter == tf) {
filteredAttributes = savedAttributes;
}
}
}
if (filteredAttributes == attributes) {
Hashtable filterTable = new Hashtable(attributes.Count);
if (attributes != null) {
foreach (Attribute attr in attributes) {
filterTable[attr.TypeId] = attr;
}
}
bool cache = tf.FilterAttributes((IComponent)component, filterTable);
Attribute[] temp = new Attribute[filterTable.Values.Count];
filterTable.Values.CopyTo(temp, 0);
filteredAttributes = new AttributeCollection(temp);
if (ds != null && cache) {
lock(ds) {
ds.SetValue(typeof(AttributeCollection), filteredAttributes);
ds.SetValue(typeof(ITypeDescriptorFilterService), tf);
}
}
}
}
}
return filteredAttributes;
}