public static EventDescriptorCollection GetEvents(object component, Attribute[] attributes, bool noCustomTypeDesc)
{
if (component == null)
{
Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
return new EventDescriptorCollection(null, true);
}
// We create a sort of pipeline for mucking with metadata. The pipeline
// goes through the following process:
//
// 1. Merge metadata from extenders.
// 2. Allow services to filter the metadata
// 3. If an attribute filter was specified, apply that.
//
// The goal here is speed. We get speed by not copying or
// allocating memory. We do this by allowing each phase of the
// pipeline to cache its data in the object cache. If
// a phase makes a change to the results, this change must cause
// successive phases to recompute their results as well. "Results" is
// always a collection, and the various stages of the pipeline may
// replace or modify this collection (depending on if it's a
// read-only IList or not). It is possible for the orignal
// descriptor or attribute collection to pass through the entire
// pipeline without modification.
//
ICustomTypeDescriptor typeDesc = GetDescriptor(component, noCustomTypeDesc);
ICollection results;
// If we are handed a custom type descriptor we have several choices of action
// we can take. If noCustomTypeDesc is true, it means that the custom type
// descriptor is trying to find a baseline set of events. In this case
// we should merge in extended events, but we do not let designers filter
// because we're not done with the event set yet. If noCustomTypeDesc
// is false, we don't do extender events because the custom type descriptor
// has already added them. In this case, we are doing a final pass so we
// want to apply filtering. Finally, if the incoming object is not a custom
// type descriptor, we do extenders and the filter.
//
if (component is ICustomTypeDescriptor)
{
results = typeDesc.GetEvents(attributes);
if (noCustomTypeDesc)
{
ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
if (extDesc != null)
{
ICollection extResults = extDesc.GetEvents(attributes);
results = PipelineMerge(PIPELINE_EVENTS, results, extResults, component, null);
}
}
else
{
results = PipelineFilter(PIPELINE_EVENTS, results, component, null);
results = PipelineAttributeFilter(PIPELINE_EVENTS, results, attributes, component, null);
}
}
else
{
IDictionary cache = GetCache(component);
results = typeDesc.GetEvents(attributes);
results = PipelineInitialize(PIPELINE_EVENTS, results, cache);
ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
if (extDesc != null)
{
ICollection extResults = extDesc.GetEvents(attributes);
results = PipelineMerge(PIPELINE_EVENTS, results, extResults, component, cache);
}
results = PipelineFilter(PIPELINE_EVENTS, results, component, cache);
results = PipelineAttributeFilter(PIPELINE_EVENTS, results, attributes, component, cache);
}
EventDescriptorCollection evts = results as EventDescriptorCollection;
if (evts == null)
{
EventDescriptor[] eventArray = new EventDescriptor[results.Count];
results.CopyTo(eventArray, 0);
evts = new EventDescriptorCollection(eventArray, true);
}
return evts;
}