File: cdf\src\NetFx40\Tools\System.Activities.Presentation\System\Activities\Presentation\View\TypeResolvingOptions.cs
Project: ndp\System.Data.csproj (System.Data)
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//----------------------------------------------------------------
namespace System.Activities.Presentation.View
{
    using System.Runtime;
    using System.Collections.ObjectModel;
    using System.Diagnostics.CodeAnalysis;
    using System.Collections.Generic;
 
    [Fx.Tag.XamlVisible(false)]
    public class TypeResolvingOptions
    {
        private IDictionary<string, string> hintTextMap;
 
        public TypeResolvingOptions() : this(null)
        {
        }
 
        public TypeResolvingOptions(IEnumerable<Type> defaultTypes)
        {
            if (defaultTypes != null)
            {
                this.MostRecentlyUsedTypes = new ObservableCollection<Type>();
                foreach (Type item in defaultTypes)
                {
                    if (item == null)
                    {
                        throw FxTrace.Exception.AsError(new ArgumentException(SR.TypeResolvingOptionsArgumentExceptionMessage));
                    }
                    this.MostRecentlyUsedTypes.Add(item);
                }
            }
        }
 
        public Func<Type, bool> Filter
        {
            get;
            set;
        }
 
        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.CollectionPropertiesShouldBeReadOnly,
            Justification = "Setter is provided to data binding on this property.")]
        internal ObservableCollection<Type> MostRecentlyUsedTypes
        {
            get;
            set;
        }
 
        /// <summary>
        /// A dictionary that maps the name of a generic type argument to a hint text.
        /// </summary>
        internal IDictionary<string, string> HintTextMap
        {
            get
            {
                if (this.hintTextMap == null)
                {
                    this.hintTextMap = new Dictionary<string, string>();
                }
 
                return this.hintTextMap;
            }
        }
 
        public bool BrowseTypeDirectly
        {
            get;
            set;
        }
 
        internal static TypeResolvingOptions Merge(TypeResolvingOptions lhs, TypeResolvingOptions rhs)
        {
            if (lhs == null)
            {
                return rhs;
            }
            else if (rhs == null)
            {
                return lhs;
            }
 
            TypeResolvingOptions result = new TypeResolvingOptions
            {
                Filter = FuncAnd(lhs.Filter, rhs.Filter),
                MostRecentlyUsedTypes = Intersect(lhs.MostRecentlyUsedTypes, rhs.MostRecentlyUsedTypes),
                BrowseTypeDirectly = lhs.BrowseTypeDirectly && rhs.BrowseTypeDirectly
            };
 
            // Pass in the fields directly to prevent triggering lazy initialization.
            IDictionary<string, string> mergedHintTextMap = MergeDictionaries<string, string>(lhs.hintTextMap, rhs.hintTextMap);
            if (mergedHintTextMap != null && mergedHintTextMap.Count > 0)
            {
                foreach (KeyValuePair<string, string> kvp in mergedHintTextMap)
                {
                    result.HintTextMap.Add(kvp.Key, kvp.Value);
                }
            }
 
            return result;
        }
 
        static Func<Type, bool> FuncAnd(Func<Type, bool> lhs, Func<Type, bool> rhs)
        {
            if (lhs == null)
            {
                return rhs;
            }
            else if (rhs == null)
            {
                return lhs;
            }
 
            return new Func<Type, bool>((e) => lhs(e) && rhs(e));
        }
 
        static ObservableCollection<T> Intersect<T>(ObservableCollection<T> lhs, ObservableCollection<T> rhs)
        {
            if (lhs == null)
            {
                return rhs;
            }
            else if (rhs == null)
            {
                return lhs;
            }
 
            ObservableCollection<T> collection = new ObservableCollection<T>();
            foreach (T t in lhs)
            {
                if (rhs.Contains(t))
                {
                    collection.Add(t);
                }
            }
 
            return collection;
        }
 
        static IDictionary<TKey, TValue> MergeDictionaries<TKey, TValue>(IDictionary<TKey, TValue> lhs, IDictionary<TKey, TValue> rhs)
        {
            if (lhs == null || lhs.Count == 0)
            {
                return rhs;
            }
 
            if (rhs == null || rhs.Count == 0)
            {
                return lhs;
            }
 
            Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>();
            foreach (KeyValuePair<TKey, TValue> kvp in lhs)
            {
                result.Add(kvp.Key, kvp.Value);
            }
 
            foreach (KeyValuePair<TKey, TValue> kvp in rhs)
            {
                if (!result.ContainsKey(kvp.Key))
                {
                    result.Add(kvp.Key, kvp.Value);
                }
            }
 
            return result;
        }
    }
}