/// <summary>
        /// Adds a new object to the DataObjects dictionary using the Namespace property as the key.
        /// It also reassigns the parent data object if it has not been assigned.
        /// </summary>
        /// <param name="childDataObject">The child data object to add.</param>
        public void Add(TC childDataObject)
        {
            if (childDataObject == null)
            {
                throw new Exception("The child data object should never be null.");
            }

            if (!childDataObject.CanBeAssignedParentMetaObject(ParentDataObject))
            {
                throw new Exception(string.Format(InvalidParentTypeErrorMessage,
                                                  childDataObject.Description, childDataObject.Namespace, ParentDataObject.Description, ParentDataObject.Namespace));
            }

            var tempParentDataObject = childDataObject.ParentMetaObject;

            childDataObject.ParentMetaObject = ParentDataObject;
            if (ChildDataObjects.ContainsKey(childDataObject.Namespace))
            {
                var errorMessage = string.Format(ObjectAlreadyExistsErrorMessage,
                                                 ParentDataObject.Description, ParentDataObject.Namespace, childDataObject.Description, childDataObject.Namespace);
                childDataObject.ParentMetaObject = tempParentDataObject;
                throw new Exception(errorMessage);
            }

            if (!ChildDataObjects.TryAdd(childDataObject.Namespace, childDataObject))
            {
                throw new Exception(string.Format(ObjectAlreadyExistsErrorMessage,
                                                  ParentDataObject.Description, ParentDataObject.Namespace, childDataObject.Description, childDataObject.Namespace));
            }
        }
        /// <summary>
        /// Calls ContainsKey on underlying dictionary.
        /// </summary>
        /// <param name="key">The key to find.</param>
        /// <returns>true if the dictionary has the key, false if not.</returns>
        public bool ContainsKey(string key)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new Exception("Key parameter should never be null.");
            }

            return(ChildDataObjects.ContainsKey(key));
        }
        /// <summary>
        /// Specific constructor to initialize with a data object lookup or any IEnumerable collection of type T.
        /// </summary>
        /// <param name="parentDataObject">The parent data objects to initalize with.</param>
        /// <param name="childDataObjects">The chidl data objects dictionary to initalize with.</param>
        public DataObjectLookup(TP parentDataObject, IEnumerable <TC> childDataObjects)
        {
            Init(parentDataObject, null);
            foreach (var childDataObject in childDataObjects)
            {
                if (!ChildDataObjects.TryAdd(childDataObject.Namespace, childDataObject))
                {
                    throw new Exception(string.Format(ObjectAlreadyExistsErrorMessage,
                                                      ParentDataObject.Description, ParentDataObject.Namespace, childDataObject.Description, childDataObject.Namespace));
                }
            }

            _lastUsedDataObject = _childDataObjects.Count > 0
                ? _childDataObjects.First().Value
                : null;
        }
        /// <summary>
        /// Removes a data object from the internal dictionary by key.
        /// </summary>
        /// <param name="key">The key for the data object to remove.</param>
        public void Remove(string key)
        {
            if (!ChildDataObjects.ContainsKey(key))
            {
                return;
            }

            if (Constants.StringComparer.Compare(_lastUsedDataObject.Namespace, key) == 0)
            {
                _lastUsedDataObject = null;
            }

            TC childDataObject;

            ChildDataObjects.TryRemove(key, out childDataObject);
            childDataObject.ParentMetaObject = null;
        }
        /// <summary>
        /// Removes a data object from the internal dictionary by value.
        /// </summary>
        /// <param name="childDataObject">The child data object to remove.</param>
        public void Remove(TC childDataObject)
        {
            if (!ChildDataObjects.ContainsKey(childDataObject.Namespace))
            {
                return;
            }

            if (Constants.StringComparer.Compare(_lastUsedDataObject.Namespace, childDataObject.Namespace) == 0 ||
                _lastUsedDataObject.Equals(childDataObject))
            {
                _lastUsedDataObject = null;
            }

            TC childDataObjectToRemove;

            ChildDataObjects.TryRemove(childDataObject.Namespace, out childDataObjectToRemove);
            childDataObject.ParentMetaObject = null;
        }
        /// <summary>
        /// Looks up an object that implements IDataObject by Namespace.
        /// If the last used object is the same, no lookup occurs by the dictionary.
        /// </summary>
        /// <param name="key">The key in the dictionary (IDataObject.Namespace).</param>
        /// <returns>Returns the data object in the dictionary.</returns>
        public TC this[string key]
        {
            get
            {
                if (_lastUsedDataObject != null &&
                    Constants.StringComparer.Compare(key, _lastUsedDataObject.Namespace) == 0)
                {
                    return(_lastUsedDataObject);
                }

                _lastUsedDataObject = null;
                return(ChildDataObjects.TryGetValue(key, out _lastUsedDataObject)
                    ? _lastUsedDataObject
                    : null);
            }
            set
            {
                ChildDataObjects[key] = value;
                _lastUsedDataObject   = value;
            }
        }
 /// <summary>
 /// Calls clear on the underlying dictionary.
 /// Sets _lastUsedDataObject to null;
 /// </summary>
 public void Clear()
 {
     _lastUsedDataObject = null;
     ChildDataObjects.Clear();
 }