/// <summary>
        /// Merges <see cref="IPropertyContainer"/> objects to single <see cref="IPropertyContainer"/>.
        /// </summary>
        /// <param name="containers">Source objects.</param>
        /// <param name="mergeMode">Merge mode. Default: <see cref="PropertyAddMode.Set"/>.</param>
        /// <returns>New <see cref="IPropertyContainer"/> instance.</returns>
        public static IPropertyContainer Merge(
            this IEnumerable <IPropertyContainer?>?containers,
            PropertyAddMode mergeMode = PropertyAddMode.Set)
        {
            MutablePropertyContainer?merger = null;

            if (containers != null)
            {
                foreach (var container in containers)
                {
                    if (container != null)
                    {
                        if (merger == null)
                        {
                            merger = new MutablePropertyContainer(
                                sourceValues: container,
                                searchOptions: container.SearchOptions);
                            continue;
                        }

                        merger.WithValues(container, mergeMode);
                    }
                }
            }

            return(merger ?? PropertyContainer.Empty);
        }
        /// <summary>
        /// Merges <see cref="IPropertyContainer"/> objects to single <see cref="IPropertyContainer"/>.
        /// </summary>
        /// <param name="propertyContainer">Source property container.</param>
        /// <param name="otherContainer">Container to merge to source container.</param>
        /// <param name="mergeMode">Merge mode. Default: <see cref="PropertyAddMode.Set"/>.</param>
        /// <returns>New <see cref="IPropertyContainer"/> instance.</returns>
        public static IPropertyContainer Merge(
            this IPropertyContainer propertyContainer,
            IPropertyContainer otherContainer,
            PropertyAddMode mergeMode = PropertyAddMode.Set)
        {
            propertyContainer.AssertArgumentNotNull(nameof(propertyContainer));
            otherContainer.AssertArgumentNotNull(nameof(otherContainer));

            return(propertyContainer.ToMutable().WithValues(otherContainer, mergeMode));
        }
        /// <summary>
        /// Merges composite properties to one container.
        /// </summary>
        /// <param name="propertyContainer">Source property container.</param>
        /// <param name="mergeMode">Merge mode. Default: <see cref="PropertyAddMode.Set"/>.</param>
        /// <param name="properties">Properties to merge.</param>
        /// <returns>New <see cref="IPropertyContainer"/> instance.</returns>
        public static IPropertyContainer MergeProperties(
            this IPropertyContainer propertyContainer,
            PropertyAddMode mergeMode = PropertyAddMode.Set,
            params IProperty <IPropertyContainer>[]?properties)
        {
            propertyContainer.AssertArgumentNotNull(nameof(propertyContainer));

            return(properties
                   .NotNull()
                   .Select(property => propertyContainer.GetValue(property))
                   .Merge(mergeMode));
        }
        /// <summary>
        /// Gets list items for property <paramref name="listProperty"/>.
        /// Then enriches each list item with common values from <paramref name="commonValues"/>.
        /// </summary>
        /// <param name="containers">Source container.</param>
        /// <param name="listProperty">List property.</param>
        /// <param name="commonValues">Property that contains common values for each list item.</param>
        /// <param name="mergeMode">Merge mode. Default: <see cref="PropertyAddMode.Set"/>.</param>
        /// <returns>List items enriched with values from <paramref name="commonValues"/>.</returns>
        public static IEnumerable <IPropertyContainer> GetListItemsEnriched(
            this IEnumerable <IPropertyContainer> containers,
            IProperty <IPropertyContainer> listProperty,
            IProperty <IPropertyContainer> commonValues,
            PropertyAddMode mergeMode = PropertyAddMode.Set)
        {
            var joinedItems = containers
                              .Select(container => new
            {
                List   = container.GetListItems(listProperty),
                Common = container.GetValue(commonValues),
            })
                              .SelectMany(a => a.List.Select(listItem => PropertyContainer.Merge(mergeMode, a.Common, listItem)));

            return(joinedItems);
        }