private static ICollection PipelineMerge(int pipelineType, ICollection primary, ICollection secondary, object instance, IDictionary cache)
{
// If there is no secondary collection, there is nothing to merge.
//
if (secondary == null || secondary.Count == 0)
{
return primary;
}
// Next, if we were given a cache, see if it has accurate data.
//
if (cache != null)
{
ICollection mergeCache = cache[s_pipelineMergeKeys[pipelineType]] as ICollection;
if (mergeCache != null && mergeCache.Count == (primary.Count + secondary.Count))
{
// Walk the merge cache.
IEnumerator mergeEnum = mergeCache.GetEnumerator();
IEnumerator primaryEnum = primary.GetEnumerator();
bool match = true;
while (primaryEnum.MoveNext() && mergeEnum.MoveNext())
{
if (primaryEnum.Current != mergeEnum.Current)
{
match = false;
break;
}
}
if (match)
{
IEnumerator secondaryEnum = secondary.GetEnumerator();
while (secondaryEnum.MoveNext() && mergeEnum.MoveNext())
{
if (secondaryEnum.Current != mergeEnum.Current)
{
match = false;
break;
}
}
}
if (match)
{
return mergeCache;
}
}
}
// Our cache didn't match. We need to merge metadata and return
// the merged copy. We create an array list here, rather than
// an array, because we want successive sections of the
// pipeline to be able to modify it.
//
ArrayList list = new ArrayList(primary.Count + secondary.Count);
foreach (object obj in primary)
{
list.Add(obj);
}
foreach (object obj in secondary)
{
list.Add(obj);
}
if (cache != null)
{
ICollection cacheValue;
switch (pipelineType)
{
case PIPELINE_ATTRIBUTES:
Attribute[] attrArray = new Attribute[list.Count];
list.CopyTo(attrArray, 0);
cacheValue = new AttributeCollection(attrArray);
break;
case PIPELINE_PROPERTIES:
PropertyDescriptor[] propArray = new PropertyDescriptor[list.Count];
list.CopyTo(propArray, 0);
cacheValue = new PropertyDescriptorCollection(propArray, true);
break;
case PIPELINE_EVENTS:
EventDescriptor[] eventArray = new EventDescriptor[list.Count];
list.CopyTo(eventArray, 0);
cacheValue = new EventDescriptorCollection(eventArray, true);
break;
default:
Debug.Fail("unknown pipeline type");
cacheValue = null;
break;
}
cache[s_pipelineMergeKeys[pipelineType]] = cacheValue;
cache.Remove(s_pipelineFilterKeys[pipelineType]);
cache.Remove(s_pipelineAttributeFilterKeys[pipelineType]);
}
return list;
}