// Optimization that speeds up the common case (single selection) private static IEnumerable <IList <ModelProperty> > GetFirstProperties(PropertyExpander expander) { IEnumerator <IEnumerable <ModelProperty> > propertyContainers = expander.GetEnumerator(); propertyContainers.MoveNext(); if (propertyContainers.Current != null) { foreach (ModelProperty property in propertyContainers.Current) { yield return(new ModelProperty[] { property }); } } }
// Optimization that speeds up the common case (single selection) private static IEnumerable <IList <ModelProperty> > GetMergedPropertiesHelper(PropertyExpander expander) { // Check empty list if (expander == null || expander.ContainerCount == 0) { return(EmptyCollection); } if (expander.ContainerCount == 1) { // Corner case - one object selected, don't bother with merging return(GetFirstProperties(expander)); } else { // Calculate the list anew return(GetMergedPropertiesCore(expander)); } }
private static IEnumerable <IList <ModelProperty> > GetMergedPropertiesCore(PropertyExpander expander) { Dictionary <string, IList <ModelProperty> > counter = new Dictionary <string, IList <ModelProperty> >(); int containerCounter = 0; foreach (IEnumerable <ModelProperty> properties in expander) { if (properties == null) { yield break; } foreach (ModelProperty property in properties) { IList <ModelProperty> existingModelPropertiesForProperty; if (!counter.TryGetValue(property.Name, out existingModelPropertiesForProperty)) { if (containerCounter == 0) { existingModelPropertiesForProperty = new List <ModelProperty>(expander.ContainerCount); counter[property.Name] = existingModelPropertiesForProperty; } else { // This property has not been encountered yet in the previous objects, // so skip it altogether. continue; } } if (existingModelPropertiesForProperty.Count < containerCounter) { // There has been a ModelItem in the list that didn't have this property, // so delete any record of it and skip it in the future. counter.Remove(property.Name); continue; } // Verify that the properties are equivalent if (containerCounter > 0 && !ModelUtilities.AreEquivalent( existingModelPropertiesForProperty[containerCounter - 1], property)) { // They are not, so scrap this property altogether counter.Remove(property.Name); continue; } existingModelPropertiesForProperty.Add(property); } containerCounter++; } foreach (KeyValuePair <string, IList <ModelProperty> > pair in counter) { // Once again, if there is a property that is not shared by all // selected items, ignore it if (pair.Value.Count < containerCounter) { continue; } // We should not set the same instance to multiple properties, // so ignore types that are not value type or string in case of multi-selection if (pair.Value.Count > 1 && !(pair.Value[0].PropertyType.IsValueType || pair.Value[0].PropertyType.Equals(typeof(string)))) { continue; } yield return((IList <ModelProperty>)pair.Value); } }