Example #1
0
        /// <summary>
        /// Indexer
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public object this[string key]
        {
            get
            {
                DataObject obj = this.FindRecursive(key);

                if (obj is null)
                {
                    throw new KeyNotFoundException();
                }

                return(obj.GetValue());
            }
            set
            {
                DataObject obj = this.FindRecursive(key);

                if (obj is null)
                {
                    throw new KeyNotFoundException();
                }

                obj.SetValue(value);
            }
        }
        /// <summary>
        /// Takes in 2 <see cref="IDataContainer"/> returns new instance of <see cref="IDataContainer"/>
        /// which containes properties which are both in LHS and RHS, the values will be from LHS
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <returns>LHS ^ RHS</returns>
        public static IDataContainer Intersect(this IDataContainer lhs, IDataContainer rhs)
        {
            IDataContainer intersect = lhs is IPropertyContainer
                ? (IDataContainer) new PropertyContainer()
                : new DataContainer();

            intersect.Name = lhs.Name;

            var lhsKeys = lhs.GetKeys();
            var rhsKeys = rhs.GetKeys();

            var intersectKeys = lhsKeys.Intersect(rhsKeys);

            foreach (var key in intersectKeys)
            {
                DataObject first = lhs.Find(key);

                // in case of nested IDataContainer
                if (first.GetValue() is IDataContainer dc)
                {
                    var second = rhs.Find(first.Name).GetValue() as IDataContainer;

                    if (dc.IsIdentical(second) == false)
                    {
                        first.SetValue(dc.Intersect(second));
                    }
                }

                intersect.Add(first);
            }

            return(intersect);
        }
        /// <summary>
        /// Add new properties from second to first, if they already exist, keep the values.
        /// Same as <see cref="Union(IDataContainer, IDataContainer)"/> but does operation inplace instead of returning new intance;
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        public static bool Merge(this IDataContainer lhs, IDataContainer rhs)
        {
            bool result      = false;
            bool innerResult = false;

            foreach (var data in rhs)
            {
                if (lhs.ContainsData(data.Name) == false)
                {
                    lhs.Add(data);
                    result = true;
                }
                else
                {
                    DataObject lhsData = lhs.Find(data.Name);

                    // No need to update value, but update the details
                    if (data is PropertyObject propRhs && lhsData is PropertyObject propLhs)
                    {
                        result = propLhs.DisplayName != propRhs.DisplayName ||
                                 propLhs.Category != propRhs.Category ||
                                 propLhs.Description != propRhs.Description;

                        propLhs.DisplayName = propRhs.DisplayName;
                        propLhs.Category    = propRhs.Category;
                        propLhs.Description = propRhs.Description;
                    }

                    if (lhsData.GetValue() is IDataContainer dc)
                    {
                        IDataContainer rhsDC = data.GetValue() as IDataContainer;
                        bool           temp  = dc.Merge(rhsDC);

                        innerResult = temp || innerResult;
                    }
                }
            }

            return(result || innerResult);
        }
        /// <summary>
        /// Reload values from file again
        /// Doesn't need new properties if added, only updates existing ones
        /// </summary>
        /// <param name="dc"></param>
        public static void Refresh(this IDataContainer dc, IDataContainer changed)
        {
            foreach (var data in changed)
            {
                object value = data.GetValue();

                if (value is IDataContainer changedChild)
                {
                    DataObject dcChild = dc.Find(data.Name);

                    if (dcChild != null)
                    {
                        IDataContainer dcChildValue = dcChild.GetValue() as IDataContainer;
                        dcChildValue.Refresh(changedChild);
                    }
                }
                else
                {
                    dc.SetValue(data.Name, value);
                }
            }
        }
 /// <summary>
 /// Implementation for <see cref="PropertyDescriptor.GetValue(object)"/>
 /// </summary>
 /// <param name="component"></param>
 /// <returns></returns>
 public override object GetValue(object component)
 {
     return(DataObject is IEditorValueProvider icvp
         ? icvp.GetEditorValue()
         : DataObject.GetValue());
 }