/// <summary>
        /// Creates a <see cref="DispatcherValueCollection"/> initialized with the specified <paramref name="values"/>.
        /// </summary>
        /// <param name="values">An object to initialize the dictionary. The value can be of type
        /// <see cref="IDictionary{TKey, TValue}"/> or <see cref="IReadOnlyDictionary{TKey, TValue}"/>
        /// or an object with public properties as key-value pairs.
        /// </param>
        /// <remarks>
        /// If the value is a dictionary or other <see cref="IEnumerable{T}"/> of <see cref="KeyValuePair{String, Object}"/>,
        /// then its entries are copied. Otherwise the object is interpreted as a set of key-value pairs where the
        /// property names are keys, and property values are the values, and copied into the dictionary.
        /// Only public instance non-index properties are considered.
        /// </remarks>
        public DispatcherValueCollection(object values)
        {
            var dictionary = values as DispatcherValueCollection;

            if (dictionary != null)
            {
                var listStorage = dictionary._storage as ListStorage;
                if (listStorage != null)
                {
                    _storage = new ListStorage(listStorage);
                    return;
                }

                var propertyStorage = dictionary._storage as PropertyStorage;
                if (propertyStorage != null)
                {
                    // PropertyStorage is immutable so we can just copy it.
                    _storage = dictionary._storage;
                    return;
                }

                // If we get here, it's an EmptyStorage.
                _storage = EmptyStorage.Instance;
                return;
            }

            var keyValueEnumerable = values as IEnumerable <KeyValuePair <string, object> >;

            if (keyValueEnumerable != null)
            {
                var listStorage = new ListStorage();
                _storage = listStorage;
                foreach (var kvp in keyValueEnumerable)
                {
                    if (listStorage.ContainsKey(kvp.Key))
                    {
                        var message = Resources.FormatDispatcherValueCollection_DuplicateKey(kvp.Key, nameof(DispatcherValueCollection));
                        throw new ArgumentException(message, nameof(values));
                    }

                    listStorage.Add(kvp);
                }

                return;
            }

            var stringValueEnumerable = values as IEnumerable <KeyValuePair <string, string> >;

            if (stringValueEnumerable != null)
            {
                var listStorage = new ListStorage();
                _storage = listStorage;
                foreach (var kvp in stringValueEnumerable)
                {
                    if (listStorage.ContainsKey(kvp.Key))
                    {
                        var message = Resources.FormatDispatcherValueCollection_DuplicateKey(kvp.Key, nameof(DispatcherValueCollection));
                        throw new ArgumentException(message, nameof(values));
                    }

                    listStorage.Add(new KeyValuePair <string, object>(kvp.Key, kvp.Value));
                }

                return;
            }

            if (values != null)
            {
                _storage = new PropertyStorage(values);
                return;
            }

            _storage = EmptyStorage.Instance;
        }
        /// <summary>
        /// Creates a <see cref="RouteValueDictionary"/> initialized with the specified <paramref name="values"/>.
        /// </summary>
        /// <param name="values">An object to initialize the dictionary. The value can be of type
        /// <see cref="IDictionary{TKey, TValue}"/> or <see cref="IReadOnlyDictionary{TKey, TValue}"/>
        /// or an object with public properties as key-value pairs.
        /// </param>
        /// <remarks>
        /// If the value is a dictionary or other <see cref="IEnumerable{T}"/> of <see cref="KeyValuePair{String, Object}"/>,
        /// then its entries are copied. Otherwise the object is interpreted as a set of key-value pairs where the
        /// property names are keys, and property values are the values, and copied into the dictionary.
        /// Only public instance non-index properties are considered.
        /// </remarks>
        public RouteValueDictionary(object values)
        {
            var dictionary = values as RouteValueDictionary;

            if (dictionary != null)
            {
                var listStorage = dictionary._storage as ListStorage;
                if (listStorage != null)
                {
                    _storage = new ListStorage(listStorage);
                    return;
                }

                Storage propertyStorage = null;// dictionary._storage as PropertyStorage;
                if (propertyStorage != null)
                {
                    // PropertyStorage is immutable so we can just copy it.
                    _storage = dictionary._storage;
                    return;
                }

                // If we get here, it's an EmptyStorage.
                _storage = EmptyStorage.Instance;
                return;
            }

            var keyValueEnumerable = values as IEnumerable <KeyValuePair <string, object> >;

            if (keyValueEnumerable != null)
            {
                var listStorage = new ListStorage();
                _storage = listStorage;
                foreach (var kvp in keyValueEnumerable)
                {
                    if (listStorage.ContainsKey(kvp.Key))
                    {
                        var message = $"the key {kvp.Key} is exist";// Resources.FormatRouteValueDictionary_DuplicateKey(kvp.Key, nameof(RouteValueDictionary));
                        throw new ArgumentException(message, nameof(values));
                    }

                    listStorage.Add(kvp);
                }

                return;
            }

            var stringValueEnumerable = values as IEnumerable <KeyValuePair <string, string> >;

            if (stringValueEnumerable != null)
            {
                var listStorage = new ListStorage();
                _storage = listStorage;
                foreach (var kvp in stringValueEnumerable)
                {
                    if (listStorage.ContainsKey(kvp.Key))
                    {
                        var message = $"the key {kvp.Key} is exist";/// Resources.FormatRouteValueDictionary_DuplicateKey(kvp.Key, nameof(RouteValueDictionary));
                        throw new ArgumentException(message, nameof(values));
                    }

                    listStorage.Add(new KeyValuePair <string, object>(kvp.Key, kvp.Value));
                }

                return;
            }

            //if (values != null)
            //{
            //    _storage = new PropertyStorage(values);
            //    return;
            //}

            _storage = EmptyStorage.Instance;
        }