// 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);
            }
        }