/// <summary>
        /// Creates a DataObject implementation that serializes to <paramref name="format"/>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <param name="format"></param>
        /// <param name="propertyBuilder"></param>
        /// <returns></returns>
        public PropertyContainerBuilder Property <T>(string name, T value, SerializationFormat format, Action <PropertyObjectBuilder> propertyBuilder = null)
            where T : class, new()
        {
            if (config.ContainsData(name) || value is null)
            {
                DataContainerEvents.NotifyInformation($"Attempted to add invalid value : {name}");

                return(this);
            }

            PropertyObject obj;

            if (format == SerializationFormat.Container)
            {
                obj = DataObjectFactory.GetPropertyObjectFor(name, value);
            }
            else if (format == SerializationFormat.Json)
            {
                obj = new JsonPropertyObject(name, value);
            }
            else if (format == SerializationFormat.Xml)
            {
                obj = new XmlPropertyObject(name, value);
            }
            else
            {
                throw new NotImplementedException();
            }

            propertyBuilder?.Invoke(new PropertyObjectBuilder(obj));

            config.Add(obj);

            return(this);
        }
        /// <summary>
        /// Function for List initializer
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Add(string key, object value)
        {
            if (IdentifierExtensions.IsValidIdentifier(key) == false)
            {
                throw new ArgumentException($"{key} is not a valid c# identifier");
            }

            internalDictionary.Add(key, DataObjectFactory.GetPropertyObjectFor(key, value));

            RaiseCollectionChanged(NotifyCollectionChangedAction.Add, internalDictionary[key]);
        }
        /// <summary>
        /// Generic method to create all types of objects
        /// Addes a different implementation of <see cref="PropertyObject"/> based on <see cref="Type"/>
        /// of <paramref name="value"/>
        /// </summary>
        /// <param name="name">name of property to be added</param>
        /// <param name="value">value of property</param>
        /// <param name="propertyBuilder">builder to set additional properties of <see cref="PropertyObject"/></param>
        /// <returns></returns>
        public PropertyContainerBuilder Property(string name, object value, Action <PropertyObjectBuilder> propertyBuilder = null)
        {
            if (config.ContainsData(name) || value is null)
            {
                DataContainerEvents.NotifyInformation($"Attempted to add invalid value : {name}");
                return(this);
            }

            if (DataObjectFactory.GetPropertyObjectFor(name, value) is PropertyObject obj)
            {
                propertyBuilder?.Invoke(new PropertyObjectBuilder(obj));

                config.Add(obj);
            }

            return(this);
        }
 public static void PutValue(this IDataContainer container, string key, object value)
 {
     if (container.ContainsData(key))
     {
         container.SetValue(key, value);
     }
     else
     {
         if (container is IPropertyContainer)
         {
             container.Add(DataObjectFactory.GetPropertyObjectFor(key, value));
         }
         else
         {
             container.Add(DataObjectFactory.GetDataObjectFor(key, value));
         }
     }
 }
        /// <summary>
        /// Generic method for adding numeric types
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <param name="propertyBuilder"></param>
        /// <returns></returns>
        public PropertyContainerBuilder Number <T>(string name, T value, Action <NumericPropertyObjectBuilder <T> > propertyBuilder = null)
            where T : struct, IComparable, IComparable <T>, IConvertible, IEquatable <T>, IFormattable
        {
            if (config.ContainsData(name))
            {
                DataContainerEvents.NotifyInformation($"Attempted to add invalid value : {name}");

                return(this);
            }

            if (DataObjectFactory.GetPropertyObjectFor(name, value) is PropertyObject obj)
            {
                propertyBuilder?.Invoke(new NumericPropertyObjectBuilder <T>(obj));

                config.Add(obj);
            }

            return(this);
        }
        /// <summary>
        /// Method used internally to create <see cref="IPropertyContainer"/> from CLR objects
        /// </summary>
        /// <param name="pi"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        private PropertyContainerBuilder Property(PropertyInfo pi, object obj)
        {
            if (pi.GetValue(obj) is object value)
            {
                var option      = pi.GetBrowseOption();
                var description = pi.GetDescription();
                var category    = pi.GetCategory();
                var displayName = pi.GetDisplayName();

                // Why is this here ??
                if (value is IDataContainer dc && dc.Count == 0)
                {
                    return(this);
                }

                config.Add(DataObjectFactory.GetPropertyObjectFor(pi.Name, value)?
                           .SetBrowsePermission(option)
                           .SetDescription(description)
                           .SetCategory(category)
                           .SetDisplayName(displayName));
            }

            return(this);
        }